C #: pasar el método nulo a sobrecargado, ¿qué método se llama?

Digamos que tengo dos versiones sobrecargadas de un método C #:

void Method( TypeA a ) { } void Method( TypeB b ) { } 

Llamo al método con:

 Method( null ); 

¿Qué sobrecarga del método se llama? ¿Qué puedo hacer para garantizar que se llame a una sobrecarga en particular?

Depende de TypeA y TypeB .

  • Si exactamente uno de ellos es aplicable (por ejemplo, no hay conversión de null a Tipo TypeA porque es un tipo de valor pero TypeA es un tipo de referencia), entonces la llamada se realizará a la correspondiente.
  • De lo contrario, depende de la relación entre TypeA y TypeB .
    • Si hay una conversión implícita de TypeA a TypeB pero no hay conversión implícita de TypeB a TypeA se utilizará la sobrecarga que utiliza TypeA .
    • Si hay una conversión implícita de TypeB a TypeA pero no hay conversión implícita de TypeA a TypeB entonces se TypeA la sobrecarga usando TypeB .
    • De lo contrario, la llamada es ambigua y no podrá comstackrse.

Consulte la sección 7.4.3.4 de la especificación C # 3.0 para ver las reglas detalladas.

Aquí hay un ejemplo de que no es ambiguo. Aquí TypeB deriva de TypeA , lo que significa que hay una conversión implícita de TypeB a TypeA , pero no al revés. Por lo tanto, se utiliza la sobrecarga con TypeB :

 using System; class TypeA {} class TypeB : TypeA {} class Program { static void Foo(TypeA x) { Console.WriteLine("Foo(TypeA)"); } static void Foo(TypeB x) { Console.WriteLine("Foo(TypeB)"); } static void Main() { Foo(null); // Prints Foo(TypeB) } } 

En general, incluso frente a una llamada por lo demás ambigua, para garantizar que se utiliza una sobrecarga en particular, simplemente envíe:

 Foo((TypeA) null); 

o

 Foo((TypeB) null); 

Tenga en cuenta que si esto implica herencia en las clases declarantes (es decir, una clase está sobrecargando un método declarado por su clase base), usted está en un problema completamente diferente, y necesita lanzar el objective del método en lugar del argumento.

Jon Skeet ha dado una respuesta completa, pero desde el punto de vista del diseño no debe depender de los casos de esquina de la especificación del comstackdor. Si nada más, si tiene que buscar lo que hace antes de escribirlo, la siguiente persona que intente leerlo tampoco sabrá qué es lo que hace. No es mantenible.

Las sobrecargas están ahí por conveniencia, y dos sobrecargas diferentes con el mismo nombre deberían hacer lo mismo. Si los dos métodos hacen cosas diferentes, cambie el nombre de uno o ambos.

Es más habitual que un método sobrecargado tenga variantes con números variables de parámetros, y para la sobrecarga con menos parámetros para proporcionar valores predeterminados razonables.

por ejemplo, la string ToString(string format, System.IFormatProvider provider) tiene la mayoría de los parámetros,
string ToString(System.IFormatProvider provider) proporciona un formato predeterminado, y
string ToString() proporciona un formato y proveedor predeterminados,

Jon Skeet ya respondió qué sobrecarga se elige de manera predeterminada, pero si quiere asegurarse de que se llame a una sobrecarga en particular, a menudo es mejor usar parámetros nombrados que emitidos.

Si usted tiene:

 void Method( TypeA a ) { } void Method( TypeB b ) { } 

Puede llamar a Method(a: null); o Method(b: null);

llamada ambigua (error de tiempo de comstackción).

Una solución simple es crear otro método con la firma de:

 void Method() { } 

o mejor para actualizar la firma en uno de los métodos para ser:

 void Method( TypeB b = null ) { } 

y luego llámalo así:

 Method(); 

En tiempo de comstackción, el valor null está null tipo y, por lo tanto, el comstackdor no puede emparejarlo con una de las firmas de método. En tiempo de ejecución, cualquier variable que pueda resolverse como null seguirá escribiéndose y por lo tanto no causará ningún problema.