Pregunta

Dado:

interface I
{
}

class B: I
{
}

class C: I
{
}

class A
{

    public void Method(B arg)
    {
    }

    public void Method(C arg)
    {
    }

    public void Method(I arg)
    {
       // THIS is the method I want to simplify.
       if (I is B)
       {
          this.Method(arg as B);
       }
       else if (I is C)
       {
          this.Method(arg as C);
       }
    }
}

Sé que hay mejores formas de diseñar este tipo de interacciones, pero debido a detalles que tomarían demasiado tiempo para explicar esto no son posibles. Dado que este patrón se duplicará MUCHAS veces, me gustaría reemplazar el lógica condicional con una implementación genérica que podría usar solo una línea. No puedo ver una manera simple de implementar este método / clase genérico, pero mis instintos me dicen que debería ser posible.

Cualquier ayuda sería apreciada.

¿Fue útil?

Solución

Lo que quiere es doble despacho , y patrón de visitante en particular.

Otros consejos

Pondría el método dentro de la interfaz y luego dejaría que el polimorfismo decidiera a qué método llamar

interface I
{
   void Method();
}

class B : I
{
   public void Method() { /* previously A.Method(B) */}
}

class C : I
{
   public void Method() { /* previously A.Method(C) */ }
}

class A
{
   public void Method(I obj)
   { 
     obj.Method();
   }
}

Ahora, cuando necesita agregar una nueva clase, solo necesita implementar I.Method. No necesitas tocar A.Method.

Esto es un poco feo, pero hace el trabajo:

public void Method(B arg)
{
  if (arg == null) return;
...
}
public void Method(C arg)
{
  if (arg == null) return;
...
}

public void Method(I arg)
{
  this.Method(arg as B);
  this.Method(arg as C);
}

Sin embargo, no creo que lo haga de esta manera. Realmente duele mirar eso. Lamento haberles obligado a todos a mirar esto también.

interface I
{ 
} 

class B : I
{
}

class C : I
{
}    

class A 
{
    public void Method(B arg)
    {
        Console.WriteLine("I'm in B");
    }

    public void Method(C arg)
    {
        Console.WriteLine("I'm in C");
    }

    public void Method(I arg)
    {
        Type type = arg.GetType();

        MethodInfo method = typeof(A).GetMethod("Method", new Type[] { type });
        method.Invoke(this, new I[] { arg });
    }
}

No existe de forma conveniente dentro de C # - vea aquí para una idea basado en la coincidencia de patrones de F #, eso hace exactamente lo que desea. Puede hacer algunas cosas con reflexión para seleccionar la sobrecarga en el tiempo de ejecución, pero eso será muy lento y tendrá problemas graves si algo satisface ambas sobrecargas. Si tuviera un valor de retorno, podría usar el operador condicional;

return (I is B) ? Method((B)I) : ((I is C) ? Method((C)I) : 0);

Nuevamente, no es bonito.

Fácil. En Visual Basic, hago esto todo el tiempo usando CallByName.

Sub MethodBase(value as Object)
    CallByName(Me, "RealMethod", CallType.Method, value)

Esto llamará a la sobrecarga de RealMethod que más se acerque al tipo de valor de tiempo de ejecución.

Estoy seguro de que puede usar CallByName desde C # importando Microsoft.VisualBasic.Interaction o creando su propia versión usando la reflexión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top