c# - tag - ¿Por qué no se compilará este código.NET aparentemente correcto?
generar documentacion visual studio 2017 (5)
Pregunto en caso de que me esté perdiendo algo obvio, pero creo que me he tropezado con un error en el compilador de .NET.
Tengo dos proyectos en una solución .NET, uno visual básico, un C #.
Código de C #, que consta de tres métodos estáticos sobrecargados con valores predeterminados:
public static class Class1
{
public static void TestFunc(int val1, int val2 = 0)
{
}
public static void TestFunc(int val1 = 0)
{
}
public static void TestFunc(string val1, int val2 = 0)
{
}
}
Código básico visual, llamando a uno de los métodos sobrecargados:
Option Explicit On
Option Strict On
Imports ClassLibrary1
Module Module1
Sub Main()
Dim x As Integer
Class1.TestFunc(x, 0)
End Sub
End Module
La compilación de este código fallará, diciendo:
''TestFunc'' es ambiguo porque existen varios tipos de miembros con este nombre en la clase ''ClassLibrary1.Class1''.
¿Por qué vería este método como ambiguo? Solo hay un Class1.TestFunc con una firma (int, int). ¿Es esto un error, o me estoy perdiendo algo?
Editar
Cuando esta pregunta se publicó por primera vez:
Option Strict On
y
Option Explicit On
no se incluyeron en la pregunta por lo que esto cambia la respuesta de forma drástica.
Respuesta original antes de la edición de la pregunta
Porque esto:
public static void TestFunc(int val1, int val2 = 0)
{
}
Es ambiguo para:
public static void TestFunc(string val1, int val2 = 0)
{
}
VB.net puede convertir un entero en una cadena.
En última instancia, parece reducirse a cómo C # está implementando los parámetros opcionales en su primer método estático. Si elimina el valor predeterminado en eso, su solución debería compilarse.
public static void TestFunc(int val1, int val2)
{
}
De hecho, en este caso, estoy algo sorprendido de que compile C #. Debe usar parámetros opcionales en C # o sobrecargas, pero no en ambos. Por ejemplo, ¿cómo eliminarías la ambigüedad de lo siguiente?
public static void TestFunc(int val1, int val2 = 0)
{
}
public static void TestFunc(int val1)
{
}
Si paso lo siguiente, ¿cuál de los dos métodos debería ejecutarse, el que tiene el parámetro opcional o el segundo sin el segundo parámetro?
TestFunc(1)
Una mejor solución si desea incluir parámetros opcionales en su implementación de C # sería combinar los métodos primero y segundo y verificar su valor predeterminado según sea necesario:
public static void TestFunc(int val1, int val2 = 0)
{
}
public static void TestFunc(string val1, int val2 = 0)
{
}
Tenga en cuenta que, utilizando esta versión, VB IS puede desambiguar qué método llamar.
En la Especificación de lenguaje de Visual Basic 10 , indica eso.
Se considera que un método con parámetros opcionales tiene varias firmas, una para cada conjunto de parámetros que la persona que llama puede pasar. Por ejemplo, el siguiente método tiene tres firmas correspondientes:
Sub F(x As Short, _
Optional y As Integer = 10, _
Optional z As Long = 20)
Por lo tanto, su TestFunc(int val1, int val2 = 0)
tiene dos firmas en VB, lo que TestFunc(int val1)
conflicto con TestFunc(int val1)
por lo que TestFunc
es ambiguo.
No puedo encontrar nada en la especificación C # que dice que los parámetros opcionales se tratan como métodos con múltiples firmas. Del comportamiento que estás viendo, asumo que en C # no se considera que tengan múltiples firmas, de lo contrario obtendrías un error de compilación, lo que significa que es válido en C #. Supongo que C # elegirá el método que se llama en función de algunas reglas, ya que no puede llamar a ambos para TestFunc(0)
.
Si tratas de compilar esto en VB.NET obtendrás
Sub TestFunc(ByVal val1 As Integer, Optional ByVal val2 As Integer = 0)
End Sub
Sub TestFunc(Optional ByVal val1 As Integer = 0)
End Sub
obtendrá Public Sub TestFunc(val1 As Integer, [val2 As Integer = 0])'' and ''Public Sub TestFunc([val1 As Integer = 0])'' cannot overload each other because they differ only by optional parameters.
entonces diré que VB.NET está más limitado que C # en la sobrecarga de parámetros opcional.
TestFunc es ambiguo debido a un parámetro predeterminado. Cuando se llama a TestFunc (x), no es seguro si está llamando a TestFunc con un solo parámetro o TestFunc con los 2 parámetros por defecto. El segundo parámetro es uno por defecto.