这是VB.NET编译器中的错误还是设计错误?

时间:2011-04-11 11:39:46

标签: c# .net vb.net compiler-construction

我发现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

请注意,如果在VB中定义了重载的Foo方法,则无关紧要。唯一重要的是呼叫站点在VB中。

VB编译器将报告错误:

  

重载解析失败,因为没有可访问的'Foo'对这些参数最具体:

'Public Sub Foo(Of String)(表达式为System.Linq.Expressions.Expression(Of System.Func(Of String)))':不是最具体的。

'Public Sub Foo(Of)(价值为)':不是最具体的。


添加用于比较的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)
    {

    }
}

2 个答案:

答案 0 :(得分:5)

暂时忽略“如果C#编译器执行它,它必须是正确的,因此它是VB编译器中的错误”的假设。我可以立即看到歧义:

Foo(Function() String.Empty)

可以调用T版本,用Func(Of String)代替T.或者它可以将单行lambda重新分类为表达式树,并调用Expression(Of Func(Of String))方法。没有理由一个人应该优先于另一个,事实上VB阻止你继续进行而不强迫你指定你想要的那个。

答案 1 :(得分:2)

我很确定我已经找到了这个原因,这不是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)重载。< / p>

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

相关问题