21

Tengo dos métodos sobrecargados, uno con un parámetro opcional.Métodos en conflicto sobrecargados con los parámetros opcionales

void foo(string a) { } 
void foo(string a, int b = 0) { } 

ahora me llaman:

foo("abc"); 

curiosamente la primera se llama sobrecarga. ¿por qué no la segunda sobrecarga con valor opcional puesto a cero?

Para ser honesto, esperaba que el compilador generara un error, al menos una advertencia para evitar la ejecución no intencionada del método incorrecto.

¿Cuál es la razón de este comportamiento? ¿Por qué el equipo de C# lo definió de esa manera?

+2

Este es exactamente el tipo de mal diseño del lenguaje que conduce a errores insidiosos. También podría ser fácilmente explotado por un interno para propósitos de espionaje corporativo. Desearía que bloquearan el lenguaje de permitir esto ya. –

Respuesta

27

De MSDN:

If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

14

Se prefiere una sobrecarga que no requiera ningún parámetro opcional que se complete automáticamente a una que sí lo haga. Sin embargo, no hay tal preferencia entre llenar en un argumento automáticamente y llenando en más de una - así por ejemplo, esto provocará un error de tiempo de compilación:

void Foo(int x, int y = 0, int z = 0) {} 
void Foo(int x, int y = 0) {} 
... 
Foo(5); 

Nota que Foo (5, 5) se resolvería con el segundo método, porque entonces no se requiere ningún parámetro opcional que se llena automáticamente en

Desde la sección 7.5.3.2 de la especificación C# 4:.

Otherwise if all parameters of MP have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in MQ then MP is better than MQ.

creo que en la mayoría de los casos esto es el comportamiento que la mayoría de la gente esperaría, para ser honesto. Se pone raro cuando introduces los métodos de la clase base en la mezcla, pero ese siempre ha sido el caso.

+2

Gracias por su respuesta.Todavía queda una pregunta: ¿POR QUÉ la definieron así? ¿Hay un escenario donde la sobrecarga con el parámetro opcional tiene sentido? Nunca se llamará con el valor predeterminado, ¿verdad? Pero puede conducir a errores no deseados. Sigo pensando que el compliler debería dar al menos una advertencia. Y hay otros ejemplos en los que el desarrollador tiene que decirle al compilador explícitamente que está al tanto de lo que está haciendo. Por ejemplo, si un parámetro en un método se declara como ref, necesito usar explícitamente la palabra clave ref en la llamada al método también; de lo contrario, no se compilará. – Thomas

+2

@Thomas: me temo que no tengo ninguna respuesta para el razonamiento, aunque Eric Lippert podría. Sin embargo, no me gustaría que añadiera * más * equipaje al código de llamada; después de todo, el motivo de los parámetros predeterminados es precisamente * reducir * la cantidad de código que necesita. –

7

Imagínese si fuese lo contrario. Usted tenía una aplicación. Tenía un método:

void foo(string a) { } 

Todo funcionaba bien. Ahora, desea agregar una sobrecarga más con un parámetro opcional:

void foo(string a, int b = 0) { } 

¡Boom! Todas las llamadas a métodos van al nuevo método. Cuando quieras o no. Agregar una sobrecarga de método puede causar llamadas a métodos incorrectos en toda la aplicación.

Desde mi punto de vista, en este caso, tendría muchas más oportunidades de romper su código (o el de otra persona).

Además, OptionalAttribute se ignoró en C# hasta la versión 4.0, pero puede usarlo. Y algunas personas lo usaron en el código C# para admitir ciertos escenarios de interoperabilidad con otros lenguajes, como Visual Basic, o para la interoperabilidad COM. Ahora C# lo usa para parámetros opcionales. Agregar advertencias/errores puede introducir un cambio radical para esas aplicaciones.

Puede haber algunas otras razones, pero esto es lo primero que se me viene a la mente.

+4

En su lugar, debería mostrar un error de compilación o una advertencia de análisis de código. – Monstieur

+0

@Locutus Parece que no ha leído el penúltimo párrafo de la respuesta de Alexandra. – JLRishe

Cuestiones relacionadas