C#函数使用扩展函数但VB等效没有?

Jun*_*ang 10 c# vb.net

所以我在C#中有以下代码:

public Container ConfigureSimpleInjector(IAppBuilder app)
{
    var container = new Container();

    container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    container.RegisterPackages();  

    app.Use(async (context, next) =>
    {
        using (AsyncScopedLifestyle.BeginScope(container))
        {
            await next();
        }
    });

    container.Verify();

    return container;
}
Run Code Online (Sandbox Code Playgroud)

app.Use()被定义为Owin.AppBuilderUserExtensions.Use(),看起来像这样:

public static IAppBuilder Use(this IAppBuilder app, Func<IOwinContext, Func<Task>, Task> handler);

VB等价如下:

Public Function ConfigureSimpleInjector(app As IAppBuilder) As Container
    Dim container = New Container()

    container.Options.DefaultScopedLifestyle = New AsyncScopedLifestyle()

    container.RegisterPackages()

    app.Use(Async Sub(context, [next])
                Using AsyncScopedLifestyle.BeginScope(container)
                    Await [next]()
                End Using
            End Sub)

    container.Verify()

    Return container
End Function
Run Code Online (Sandbox Code Playgroud)

出于某种原因,在VB版本中,app.Use()不使用可用的扩展功能,IAppBuilder.Use()而是简单地使用,如下所示:

Function Use(middleware As Object, ParamArray args() As Object) As IAppBuilder

为什么VB代码不使用与C#相同的扩展函数,如何使用它?

编辑

为清楚起见,扩展方法不是我自己的.他们来自Owin第三方图书馆.因此,没有重命名扩展方法的选项.

pas*_*sty 5

在C#代码因为next是Func并await 返回一个任务,没有return语句,但Task实际上返回了一个对象.

IMO VB.NET代码返回Task对象,因为lambda被指定为Sub(= Action在C#中).

更改VB.NET代码中的Subto Func应调用所需方法.


Hei*_*nzi 4

在 VB ( fiddle ) 中,当需要对象时,您可以传递 lambda 表达式:

Public Shared Sub Main()
    MyMethod(Function() True)    ' compiles
End Sub

Public Shared Sub MyMethod(o As Object)
End Sub
Run Code Online (Sandbox Code Playgroud)

在 C# ( fiddle ) 中,这是行不通的:

public static void Main()
{
    // Compilation error: Cannot convert lambda expression to type 'object' because it is not a delegate type.
    // You'd need to use: MyMethod(new Func<bool>(() => true));
    MyMethod(() => true);
}

public static void MyMethod(object o) { }
Run Code Online (Sandbox Code Playgroud)

这可能是因为 lambda 表达式可以在 VB 中隐式转换为委托,但在 C# 中则不行

public static void Main()
{
    // Compilation error: Cannot convert lambda expression to type 'object' because it is not a delegate type.
    // You'd need to use: MyMethod(new Func<bool>(() => true));
    MyMethod(() => true);
}

public static void MyMethod(object o) { }
Run Code Online (Sandbox Code Playgroud)
' Compiles
Dim d As System.Delegate = Function() True   
Run Code Online (Sandbox Code Playgroud)

因此,在您的代码示例中,VB 找到一个匹配的合适实例方法并使用它。在 C# 代码中,没有找到匹配的实例方法(因为您的 lambda 表达式不匹配object),而是使用扩展方法。

请注意,如果找到匹配的方法,两种语言都更喜欢实例方法而不是扩展方法。如果稍后添加匹配的实例方法,这可能会导致微妙的错误。


如何解决这个问题?我建议对扩展方法和实例方法使用不同的名称 - 其他开发人员将来阅读您的代码将会感谢您。如果这不是一个选项,您始终可以显式调用扩展方法:

Owin.AppBuilderUserExtensions.Use(app, Async Sub(context, [next]) ...)
Run Code Online (Sandbox Code Playgroud)