2011-10-07 19 views
29

tengo el siguiente código:parámetro de acción en el que <T1, T2, T3> T3 puede ser opcional

public static MyMethod() 
{ 
    ...Do something 
    ProtectedMethod(param1, param2); 
    ...Do something 
} 

protected static void ProtectedMethod(IEnumerable<string> param1, string param2, int param3 = 1) 
{ 
    ... Do something 
} 

Tome nota del parámetro param3 opcional.

Ahora, por varias razones, necesito extraer el código del método MyMethod en su propia clase, pero no puedo extraer ProtectedMethod con él debido a todas las clases heredadas de este y debo mantener los cambios. pequeño y aislado. Así que pensé que podría tener un delegado Action <> en la nueva clase con la misma firma que ProtectedMethod.

El problema es que si declaro el delegado de esta manera:

protected readonly Action<IEnumerable<string>, string, int> m_ProtectedMethod; 

El código extraído no le gusta porque dice que el método sólo se invoca con dos parámetros.

Y si declaro el delegado de este modo:

protected readonly Action<IEnumerable<string>, string> m_ProtectedMethod; 

Cuando lo envío como parámetro para la nueva clase que no le gusta, ya sea porque el método se define como tener tres parámetros no dos.

Hasta ahora, la única forma en que he pensado para resolver esto es crear una versión sobrecargada de ProtectedMethod para eliminar el parámetro opcional.

¿Es esta la única opción o existe otra forma de hacerlo ya que ahora la opción preferida es tener parámetros opcionales en lugar de métodos sobrecargados?

+0

nada relacionado, pero algo que se ve similar: http://stackoverflow.com/questions/707780/is-there-a-reasonable-approach-to-default-type-parameters-in-c-sharp- genéricos – nawfal

Respuesta

29

Los parámetros opcionales son un atributo de un método o parámetro delegado. Cuando llama a una firma (método o delegado) que tiene un parámetro opcional conocido en tiempo de compilación, el compilador insertará el valor del parámetro opcional en el sitio de la llamada.

El tiempo de ejecución no conoce los parámetros opcionales, por lo que no puede crear un delegado que inserte un parámetro opcional cuando se invoca.

En su lugar, tiene que declarar un tipo de delegado a medida con un parámetro opcional:

public delegate void MyDelegate(IEnumerable<string> param1, string param2, int param3 = 1); 

Al llamar a este delegado, podrá omitir el tercer parámetro, sin tener en cuenta la declaración del método (s) contiene.

+2

¿Pueden los argumentos de tipo ser opcionales? –

+0

@Joel: ¿Qué quieres decir? – SLaks

+2

@JoelCoehoorn - no - genéricos crean nuevos tipos –

1

Depende de cómo se consuma m_ProtectedMethod, pero encontré un compromiso en mi propia situación, donde uso una sobrecarga más que la otra.

Simply define a simpler (tiene parámetros menos genéricos) Acción <> variable, que invoca el método de variable de acción suministrado más complejo. Esto se puede lograr en (i) alcance local en el uso; o (ii) el alcance del objeto al asignar la propiedad de Acción o la construcción del objeto.

Como no existe la sobrecarga variable/propiedad, necesita dos nombres diferentes para las dos variables de acción relacionadas.

EG I: Ámbito local (probablemente no es el más adecuado para su escenario)

public MyMethod(Action<IEnumerable<string>, string, int> m_ProtectedMethod2) 
{ 
    Action<IEnumerable<string>, string> m_ProtectedMethod = (p1,p2) => { 
     m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter 
    } 

    ...Do something 
    m_ProtectedMethod(param1, param2); 
    ...Do something 
    ...If something 
     m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly 
    ...Do something 
} 

EG II: ámbito de los objetos

private Action<IEnumerable<string>, string, int> m_ProtectedMethod2 = null; 
private Action<IEnumerable<string>, string> m_ProtectedMethod = null; 
protected Action<IEnumerable<string>, string, int> ProtectedMethod 
{ 
    get { return m_ProtectedMethod2; } 
    set { 
     m_ProtectedMethod2 = value; 
     m_ProtectedMethod = (p1,p2) => { 
     m_ProtectedMethod2(p1,p2,1); //The value 1 is the default 3rd parameter 
     } 
    } 
} 

public MyMethod() 
{ 
    ...Do something 
    m_ProtectedMethod(param1, param2); 
    ...Do something 
    ...If something 
     m_ProtectedMethod2(param1, param2, param3); //Calling the more complex form directly 
    ...Do something 
} 

Nota en ambos casos he diseñado el valor de ajuste por defecto para ser la variable más extrañamente designada, que tiene el sufijo 2, de modo que al consumirse, la sobrecarga más simple tiene el nombre más básico de la variable.

Cuestiones relacionadas