这是VB中的一个错误吗?NET编译器或设计

本文关键字:NET 编译器 错误 一个 VB 这是 | 更新日期: 2023-09-27 17:49:45

我发现c#和vb编译器在重载解析上存在差异。我不确定这是错误还是故意的:

Public Class Class1
    Public Sub ThisBreaks()
        ' These work '
        Foo(Of String)(Function() String.Empty) 'Expression overload '
        Foo(String.Empty) 'T overload '
        ' This breaks '
        Foo(Function() String.Empty)
    End Sub
    Public Sub Foo(Of T)(ByVal value As T)
    End Sub
    Public Sub Foo(Of T)(ByVal expression As Expression(Of Func(Of T)))
    End Sub
End Class

请注意,重载foo方法是否在VB中定义并不重要。唯一重要的是调用站点是在VB中。

vb编译器会报错:

重载解析失败,因为没有可访问的'Foo'是最特定于这些参数的:

` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `表达式(系统。

'Public Sub Foo(Of)(value As)': Not most specific.


添加c#代码用于比较:

class Class1
{
    public void ThisDoesntBreakInCSharp()
    {
        Foo<string>(() => string.Empty);
        Foo(string.Empty);
        Foo(() => string.Empty);
    }
    public void Foo<T>(T value)
    {
    }
    public void Foo<T>(Expression<Func<T>> expression)
    {
    }
}

这是VB中的一个错误吗?NET编译器或设计

暂时忽略"如果c#编译器这样做,它一定是正确的,因此它是VB编译器中的错误"的假设。我可以立即看到歧义:

Foo(Function() String.Empty)

可以调用T版本,将t替换为Func(Of String),也可以将单行lambda重新分类为表达式树,调用Expression(Of Func(Of String))方法。没有理由一个应该优先于另一个,事实上,VB在没有强制您指定您想要的情况下阻止您继续。

我很确定我已经找到了这个原因,这不是vb编译器的缺点,而是c#编译器的缺点。

考虑以下在VB中是合法的:

Dim foo = Function() String.Empty

在c#中不合法:

var foo = () => string.Empty;

因此,类型推断在VB中更强一些,因为在示例Function() String.Empty中的参数可以推断为Function(Of String),这将适用于Foo(Of T)(ByVal value As T)过载。

在c#中这是不可能发生的,因为() => string.Empty不能在没有上下文的情况下推断,它可以在表达式重载中推断,但不能在t -重载中推断。