2011-02-07 14 views
302

me di cuenta de que con los parámetros opcionales en C# 4 Si especifica un parámetro como opcional en una interfaz que no tienes que hacer que el parámetro opcional en cualquier clase de aplicación:¿Por qué los parámetros opcionales C# 4 definidos en la interfaz no se aplican en la 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 sincero no estoy seguro de si debe incluso especificar valores predeterminados en la interfaz, ya que debe ser una implementación decisión.

Por otro lado, esta desconexión significa que no siempre se puede utilizar la clase concreta y la interfaz de forma intercambiable. Esto, por supuesto, no sería un problema si el valor predeterminado se especifica en la implementación, pero si expones tu clase concreta como interfaz (usando algún marco IOC para inyectar la clase concreta, por ejemplo) entonces realmente no hay punto que tiene el valor predeterminado, ya que la persona que llama tendrá que proporcionar siempre de todos modos.

+16

¿Porque son opcionales? – Oded

+1

Pero puede convertir la instancia de objeto en 'MiInterfaz' y llamarlo con el parámetro opcional:' ((MiInterfaz) obj). MétodoTest(); '. –

+5

@oded - pero si usted dice que este parámetro es opcional en el contrato, ¿por qué permite que el implementador no lo haga opcional? ¿Eso no solo causa confusión a cualquiera que quiera usar el contrato? – theburningmonk

Respuesta

193

ACTUALIZACIÓN: This question was the subject of my blog on May 12th 2011. Thanks for the great question!

Suponga que tiene una interfaz que usted describe, y un centenar de clases que implementan. Luego decide hacer que uno de los parámetros de uno de los métodos de la interfaz sea 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 que el parámetro sea opcional también?

Supongamos que lo hicimos.Ahora supongamos que el desarrollador no tiene el código fuente de la aplicació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 es el autor de D supone que para hacer este trabajo? ¿Se les exige en su mundo que llamen al autor de B por teléfono y les piden 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 volar. ¿Qué pasa si dos personas llaman al autor de B, y uno de ellos quiere que el valor predeterminado sea verdadero y uno de ellos quiere que sea falso? ¿Qué pasa si el autor de B simplemente se niega a seguir el juego?

Tal vez en ese caso, sería necesario decir:

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

La característica propuesta parece añadir un montón de inconvenientes para el programador sin un aumento correspondiente en poder representativo. ¿Cuál es el beneficio convincente de esta característica que justifica el mayor costo para el usuario?

+0

Ahora que lo pones así, no tiene sentido que exista una restricción en la clase de implementación para seguir el uso del mismo valor predeterminado que la interfaz. – theburningmonk

+0

Nunca pensé cuánto dolor podría causar eso. Supongo que la única manera de hacer que parezca que los métodos de interfaz tienen argumentos opcionales que son iguales en cualquier implementación, es tener métodos de extensión en la interfaz que manejen las sobrecargas. – Fede

+3

¿Habría alguna posibilidad de un futuro .NET que permita una definición de interfaz? para especificar implementaciones "predeterminadas"? Parecería conceptualmente sencillo: crear una clase genérica estática con algunos metadatos especiales para contener los métodos, y al construir la interfaz vtable para una clase que implementa la interfaz, complete los espacios que faltan con los correspondientes en los "métodos predeterminados" apropiados. clase. El hecho de que los métodos struct pasen 'this' por referencia mientras que los métodos de clase pasan 'this' por valor podría tratarse teniendo una clase estática para las estructuras y una para las clases. – supercat

24

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 al que se llama, sino al tipo de referencia al que se llama.

45

Un parámetro opcional se acaba de etiquetar 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 reemplaza por obj2.TestMethod(false); cuando el código C# se compila en IL, y no en JIT-time.

Por lo tanto, en cierto modo, siempre es la persona que llama 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 vuelve a compilar el código de llamada, continuará utilizando el valor predeterminado anterior.

Por otro lado, esta desconexión significa que no siempre se puede utilizar la clase de hormigón y la interfaz de forma intercambiable.

Ya no puede hacer eso si el método de interfaz era implemented explicitly.

+1

¿Se puede obligar a los implementadores a implementar explícitamente ? – crush

5

Los parámetros opcionales son algo así como una sustitución de macros 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 lo lanzas a una interfaz.

Cuestiones relacionadas