2011-04-15 18 views
25

Estaba jugando con parámetros opcionales para ver cómo funcionarían con las interfaces y me encontré con una advertencia extraña. La configuración que tenía era el siguiente código:Advertencia al implementar explícitamente una interfaz con parámetros opcionales

public interface ITestInterface 
{ 
    void TestOptional(int a = 5, int b = 10, object c = null); 
} 

public class TestClass : ITestInterface 
{ 

    void ITestInterface.TestOptional(int a = 5, int b = 5, object c = null) 
    { 
     Console.Write("a=" + a + " b=" + b + " c=" + c); 
    } 
} 

El compilador me da las siguientes advertencias:

  • El valor predeterminado especificado para el parámetro 'a' no tendrá ningún efecto porque se aplica a un miembro que se utiliza en contextos que no permiten argumentos opcionales
  • El valor predeterminado especificado para el parámetro 'b' no tendrá efecto porque se aplica a un miembro que se utiliza en contextos que no admiten argumentos opcionales
  • El valor predeterminado especificado F o parámetro 'c' no tendrá ningún efecto porque se aplica a un miembro que se utiliza en contextos que no permiten argumentos opcionales

Si funciono esto con el siguiente código:

class Program 
{ 
    static void Main(string[] args) 
    { 
     ITestInterface test = new TestClass(); 
     test.TestOptional(); 
     Console.ReadLine(); 
    } 
} 

consigo la salida de "" como era de esperar.

Mi pregunta es para qué sirve la advertencia. ¿A qué contextos se está refiriendo?

Respuesta

19

El problema con los argumentos opcionales en C# es si el destinatario de la llamada ve el objeto como TestClass o ITestInterface. En el primer caso, se aplican los valores declarados en la clase. En el segundo caso, se aplican los valores declarados en la interfaz. Es porque el compilador utiliza la información de tipo estáticamente disponible para construir la llamada. En caso de una implementación de interfaz explícita el método nunca es llamado 'para una clase', siempre 'de una interfaz'

La Especificación C# Lenguaje en 10.6.1 estados:

Si los parámetros opcionales se producen en una implementando declaración de método parcial (§10.2.7), una implementación de miembro de interfaz explícita (§13.4.1) o en una declaración de indexador de parámetro único (§10.9) el compilador debería dar una advertencia, ya que estos miembros nunca pueden ser invocados en una manera que permite que los argumentos sean omitidos.

+0

@GregC Sí, no tienen ningún efecto en caso de una implementación explícita. En el caso de una implementación implícita, lo importante es mantener los mismos valores en la interfaz y en las clases. De lo contrario, puede terminar con algunos errores muy difíciles de descubrir. –

+0

También fueron bastante difíciles de descubrir en C++, por lo que el equipo de C# optó por esperar con valores de parámetros predeterminados hasta hace poco. Creo que vi esto en el blog de Eric L., creo. – GregC

1

Craig,

Estos avisos son procedentes de los valores predeterminados especificados en la implementación método de clase. En .net, el valor predeterminado para el argumento siempre está determinado por el tipo de referencia. Y, por supuesto, con una implementación de interfaz explícita como esta, solo es posible llamar a este método a través de una referencia de interfaz, que define el valor predeterminado. Como tal, es irrelevante el valor que pongas aquí en la clase, ya que nunca se resolverá y podrás eliminarlo felizmente. Intellisense estará bien, dado que el valor predeterminado aquí nunca puede ser efectivo.

http://funcakes.posterous.com/?tag=c

http://funcakes.posterous.com/c-40-optional-parameters-default-values-and-i

+0

Su término "El tipo de referencia" en la segunda oración es un poco confuso. Podría ser útil explicar que una definición de método que implemente implícitamente una interfaz efectivamente define dos puntos de entrada; los parámetros predeterminados son honrados por uno e ignorados por el otro. Una definición explícita de interfaz solo define un punto de entrada, y los parámetros predeterminados se ignoran allí; no define ningún punto de entrada donde se respetarían los valores predeterminados. – supercat

-1

El compilador le está diciendo

void ITestInterface.TestOptional(int a = 5, int b = 5, object c = null) 

es fundamentalmente el mismo que

void ITestInterface.TestOptional(int a, int b, object c) 

La razón de ser, ya que se debe invocar TestOptional a través de la interfaz de la interfaz s upply los parámetros. No hay forma de que no se haya proporcionado un valor de parámetro en la clase.

+0

Probablemente estoy duplicando una o más de estas respuestas, pero de todos modos agregaré esta respuesta. Ninguna de las respuestas fue realmente clara sobre lo que estaban explicando, lo descubrí, pero creo que podría explicarse mejor con los ejemplos de código anteriores. –

Cuestiones relacionadas