Cosa si intende per dispatch? Per rispondere a questa domanda, osserviamo innanzitutto gli snippet di codice qua sotto 

public class Base
{
    public virtual int Metodo() { return 0; }
}

public class A : Base
{
    public override int Metodo()
    {
        return 1;
    }
}

public class B : Base
{
    public override int Metodo()
    {
        return 2;
    }
}

Definite le classi Base,A,B come sopra, cosa scriverà in Console lo snippet seguente? 

static void Main(string[] args)
{
    Base b = new Base();

    var randInt = new Random().Next(3);

    if (randInt == 1)
        b = new A();
    else if (randInt == 0)
        b = new B();

    Console.Write(b.Metodo());

}

La risposta è: dipende! Il metodo che viene risolto dipende dal tipo a run-time della variabile b. Quindi in conclusione possiamo dire che la risoluzione di un metodo non finisce a compile-time ma può dipendere dai tipi a run-time degli oggetti.

Nel caso presentato sopra il metodo non ha parametri e l'unico oggetto coinvolto è l'istanza su cui chiamiamo il metodo. Ma cosa succede se il metodo ha parametri? Come si comporta in questo caso? Dipende nuovamente dai tipi a run-time?

Proponiamo un altro snippet di codice per mostrare la situazione di cui stiamo parlando.

public class Base
{
    public virtual int Metodo() { return 0; }

    public virtual string Metodo(BaseArgument obj)
    {
        return "Base + BaseArgument";
    }

    public virtual string Metodo(SpecialArgument obj)
    {
        return "Base + SpecialArgument";
    }
}

public class A : Base
{
    public override int Metodo()
    {
        return 1;
    }

    public override string Metodo(BaseArgument obj)
    {
        return "A + BaseArgument";
    }

    public override string Metodo(SpecialArgument obj)
    {
        return "A + SpecialArgument";
    }
}

public class B : Base
{
    public override int Metodo()
    {
        return 2;
    }

    public override string Metodo(BaseArgument obj)
    {
        return "B + BaseArgument";
    }

    public override string Metodo(SpecialArgument obj)
    {
        return "B + SpecialArgument";
    }
}

public class BaseArgument
{

}

public class SpecialArgument : BaseArgument
{

}

La classe Base da cui ereditano A e B ha un metodo con due overload, uno che prende un BaseArgument e uno che prende uno SpecialArgument. Vediamo qua sotto un esempio di chiamata. Cosa scriverà stavolta in Console?

static void Main(string[] args)
{
    Base b = new A();
    BaseArgument argomento = new SpecialArgument();

    Console.Write(b.Metodo(argomento));

}

La stringa stampata è "A + BaseArgument" in quanto il metodo viene risolto con il tipo a run-time dell'oggetto su cui è chiamato ma con il tipo a compile-time dell'argomento. Questo è il comportamento che si indica con dispatch singolo. Un dispatch multiplo permetterebbe di risolvere un metodo considerando i tipi a runtime di tutti gli oggetti coinvolti.

E' possibile simulare il dispatch multiplo in C#, in uno dei prossimi post faremo vedere due tecniche possibili per farlo.
comments powered by Disqus