versión referencia proyecto net los framework existente ensamblados encuentran destino cambiar c# .net vb.net compiler-construction

c# - referencia - cambiar la versión de destino de la.net framework en un proyecto existente



¿Es esto un error en el compilador VB.NET o por diseño? (2)

He encontrado una diferencia en la resolución de sobrecarga entre el C # y el compilador VB. No estoy seguro si es un error o por diseño:

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

Tenga en cuenta que no importa si los métodos Foo sobrecargados están definidos en VB o no. Lo único que importa es que el sitio de la llamada está en VB.

El compilador VB reportará un error:

La resolución de sobrecarga falló porque ningún ''Foo'' accesible es más específico para estos argumentos:

''Public Sub Foo (Of String) (expresión As System.Linq.Expressions.Expression (Of System.Func (Of String)))'': No es el más específico.

''Public Sub Foo (Of) (value As)'': No es el más específico.

Agregando el código C # que funciona para la comparación:

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) { } }


Estoy bastante seguro de que he encontrado la razón de esto y no es una venida corta del compilador VB, pero es una venida corta del compilador C #.

Considere lo siguiente que es legal en VB:

Dim foo = Function() String.Empty

El equivalente no sería legal en c #:

var foo = () => string.Empty;

Entonces, la inferencia de tipos es un poco más fuerte en VB, debido a esto, el argumento en el ejemplo Function() String.Empty se puede inferir a Function(Of String) que sería aplicable a Foo(Of T)(ByVal value As T) sobrecarga.

En C # esto no puede suceder ya que () => string.Empty nunca se puede inferir sin contexto, se puede inferir en la expresión sobrecarga pero no en la T-sobrecarga.


Ignorando por el momento la suposición de que "si el compilador de C # lo hace, debe ser correcto, por lo tanto, es un error en el compilador de VB". Inmediatamente puedo ver la ambigüedad:

Foo(Function() String.Empty)

Podría invocar la versión T , sustituyendo Func(Of String) por T. O podría reclasificar la línea única lambda en un árbol de expresión e invocar el método de Expression(Of Func(Of String)) . No hay ninguna razón por la que uno deba ser preferido sobre el otro, y de hecho VB le impide continuar sin forzarlo a especificar cuál desea.