C# e dispatch singolo e multiplo
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.
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.