Domanda

Data:

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);
       }
    }
}

So che ci sono modi migliori per progettare questo tipo di interazioni, ma grazie a dettagli che richiederebbero troppo tempo per spiegarlo non sono possibili. Poiché questo modello verrà duplicato MOLTE volte, vorrei sostituire il logica condizionale con un'implementazione generica che potrei usare solo una riga. Non riesco a vedere un modo semplice per implementare questo metodo / classe generica, ma i miei istinti mi dicono che dovrebbe essere possibile.

Qualsiasi aiuto sarebbe apprezzato.

È stato utile?

Soluzione

Quello che vuoi è double dispatch e modello di visitatore in particolare.

Altri suggerimenti

Vorrei inserire il metodo all'interno dell'interfaccia e quindi lasciare che il polimorfismo decida quale metodo chiamare

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();
   }
}

Ora quando devi aggiungere una nuova classe, devi solo implementare I.Method. Non è necessario toccare A.Method.

Questo è un po 'brutto ma fa il suo lavoro:

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);
}

Non penso che lo farei in questo modo, però. In realtà fa male guardarlo. Mi dispiace di aver costretto tutti voi a guardare anche questo.

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 });
    }
}

Non esiste in una forma conveniente con C # - vedi qui per un'idea basato sulla corrispondenza del modello di F #, che fa esattamente quello che vuoi. Puoi fare alcune cose con la riflessione per selezionare il sovraccarico in fase di esecuzione, ma sarà molto lento e avrà gravi problemi se qualcosa soddisfa entrambi i sovraccarichi. Se avessi un valore di ritorno puoi usare l'operatore condizionale;

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

Ancora una volta - non carino.

Facile. In Visual Basic lo faccio sempre usando CallByName.

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

Questo chiamerà il sovraccarico di RealMethod che corrisponde maggiormente al tipo di valore di runtime.

Sono sicuro che puoi usare CallByName da C # importando Microsoft.VisualBasic.Interaction o creando la tua versione usando reflection.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top