Это ошибка в компиляторе VB.NET или в дизайне? - PullRequest
17 голосов
/ 11 апреля 2011

Я обнаружил разницу в разрешении перегрузки между 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 String) (выражение как System.Linq.Expressions.Expression (Of System.Func (Of String)))': Не очень конкретно.

'Public Sub Foo (Of) (значение As)': Не очень конкретно.


Добавление кода 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 ]

5 голосов
/ 11 апреля 2011

На данный момент игнорируется предположение, что «если компилятор C # делает это, он должен быть прав, поэтому это ошибка в компиляторе VB».Я сразу вижу двусмысленность:

Foo(Function() String.Empty)

Может вызвать версию T, заменяя T на Func(Of String). Или она может переклассифицировать однострочную лямбду в дерево выражений и вызвать Expression(Of Func(Of String))метод.Нет никаких причин, по которым одно должно быть предпочтительнее другого, и на самом деле VB мешает вам продолжать, не заставляя вас указывать, какой вы хотите.

2 голосов
/ 11 апреля 2011

Я почти уверен, что нашел причину этого, и это не короткое появление компилятора 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-перегрузке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...