¿Por qué los parámetros opcionales de C# 4 definidos en la interfaz no se aplican en la implementación de la clase?


Noté que con los parámetros opcionales en C # 4 si especifica un parámetro como opcional en una interfaz, NO tiene que hacer que ese parámetro sea opcional en ninguna clase de implementación:

public interface MyInterface
{
    void TestMethod(bool flag = false);
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

Y por lo tanto:

var obj = new MyClass();        
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

¿Alguien sabe por qué los parámetros opcionales están diseñados para funcionar de esta manera?

Por un lado, supongo que la capacidad de anular los valores predeterminados especificados en las interfaces es útil, aunque para ser honesto, no estoy seguro de si debería ser capaz de especificar valores por defecto en la interfaz como que debe ser una decisión de implementación.

Por otro lado, esta desconexión significa que no siempre se puede usar la clase concreta y la interfaz indistintamente. Esto, por supuesto, no sería un problema si el valor predeterminado se especifica en la implementación, pero luego si está exponiendo su clase concreta como la interfaz (utilizando algún marco de IOC para inyectar la clase concreta, por ejemplo), entonces realmente no tiene sentido tener el valor predeterminado como el la persona que llama tendrá que proporcionarlo siempre de todos modos.

Author: Kirill Kobelev, 2011-02-07

4 answers

ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog el 12 de mayo de 2011. Gracias por la gran pregunta!

Supongamos que tiene una interfaz como la describe, y un centenar de clases que la implementan. Entonces decide hacer uno de los parámetros de uno de los métodos de la interfaz opcional. ¿Está sugiriendo que lo correcto es que el compilador obligue al desarrollador a encontrar cada implementación de ese método de interfaz, y haga que el parámetro sea opcional como bien?

Supongamos que hicimos eso. Ahora supongamos que el desarrollador no tiene el código fuente para la implementación:


// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}

// in source code
interface MyInterface 
{ 
    void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

¿Cómo se supone que el autor de D haga este trabajo? ¿Están obligados en su mundo a llamar al autor de B por teléfono y pedirles que les envíen una nueva versión de B que haga que el método tenga un parámetro opcional?

Eso no va a funcionar. ¿Qué pasa si dos personas llaman al autor de B, y uno de ellos quiere el valor predeterminado es true y uno de ellos quiere que sea false? ¿Y si el autor de B simplemente se niega a seguir el juego?

Tal vez en ese caso se les requeriría decir:

class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

La característica propuesta parece agregar muchos inconvenientes para el programador sin el correspondiente aumento en el poder representativo. ¿Cuál es el beneficio convincente de esta función que justifica el aumento del costo para el usuario?

 206
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-13 22:12:11

Un parámetro opcional es simplemente etiquetado con un atributo. Este atributo le dice al compilador que inserte el valor predeterminado para ese parámetro en el sitio de llamada.

La llamada obj2.TestMethod(); se sustituye por obj2.TestMethod(false); cuando el código de C# se compila en IL, y no en tiempo JIT.

Así que, de alguna manera, siempre es la persona que llama la que proporciona el valor predeterminado con parámetros opcionales. Esto también tiene consecuencias en el control de versiones binarias: Si cambia el valor predeterminado pero no recompila el código de llamada, continúe utilizando el antiguo valor predeterminado.

Por otro lado, esta desconexión significa que no siempre se puede usar la clase concreta y la interfaz indistintamente.

Ya no puede hacer eso si el método de interfaz fue implementado explícitamente.

 45
Author: CodesInChaos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-04 15:57:29

Porque los parámetros predeterminados se resuelven en tiempo de compilación, no en tiempo de ejecución. Por lo tanto, los valores predeterminados no pertenecen al objeto que se llama, sino al tipo de referencia a través del cual se llama.

 24
Author: Olhovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-07 15:12:47

Los parámetros opcionales son como una sustitución de macro de lo que entiendo. No son realmente opcionales desde el punto de vista del método. Un artefacto de eso es el comportamiento que ves donde obtienes resultados diferentes si lanzas a una interfaz.

 5
Author: Ariel Arjona,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-07 15:15:19