2013-04-12 11 views
13

Pensavo che il metodo che viene chiamato sia deciso al runtime o mi sia sfuggito qualcosa? Esempio di codice:Perché non viene richiamato il metodo sovraccaricato?

class Program 
{ 
    static void Main(string[] args) 
    { 
     var magic = new MagicClass(); 
     magic.DoStuff(new ImplA()); 
     magic.DoStuff(new ImplB()); 
     Console.ReadLine(); 
    } 
} 
class MagicClass 
{ 
    internal void DoStuff<T>(T input) where T : SomeBase 
    { 
     HiThere(input); 
    } 

    void HiThere(SomeBase input) 
    { 
     Console.WriteLine("Base impl"); 
    } 

    void HiThere(ImplA input) 
    { 
     Console.WriteLine("ImplA"); 
    } 

    void HiThere(ImplB input) 
    { 
     Console.WriteLine("ImplB"); 
    } 
} 

abstract class SomeBase 
{ 

} 
class ImplA : SomeBase{} 
class ImplB : SomeBase{} 

ho pensato di ottenere:

ImplA 
ImplB 

come output, ma la stampa Base impl. C'è qualcosa che posso fare per ottenere il metodo sovraccarico senza trasmettere l'input?

+2

Ecco una spiegazione abbastanza decente perché: http://csharpindepth.com/Articles/General/Overloading.aspx –

risposta

18

I sovraccarichi sono scelti dal compilatore. Per la chiamata qui:

internal void DoStuff<T>(T input) where T : SomeBase 
{ 
    HiThere(input); 
} 

sceglie quello con SomeBase, perché questo è tutto quello che ha in fase di compilazione.

Quello che probabilmente si desidera è l'override. Ciò significa che la diversa logica deve essere inserita negli ereditari di SomeBase:

+2

Un'altra possibilità è che egli desideri eseguire ['double dispatch'] (http: //en.wikipedia. org/wiki/Double_dispatch) o utilizzare il ['visitor pattern'] (http://en.wikipedia.org/wiki/Visitor_pattern). –

+6

Oppure l'uso di 'dynamic':' HiThere ((dynamic) input); 'Questo sposta la risoluzione di sovraccarico nel runtime in cui è noto il tipo esatto di' input'. –

+0

@DanielHilgarth: Questa è probabilmente la migliore implementazione possibile del doppio invio. :) –

4

I sovraccarichi vengono selezionati durante la compilazione.
Le sostituzioni vengono selezionate durante il runtime.

Qui, i compilatori sanno solo che T può essere assegnato a SomeBase, ma nient'altro. In realtà, se funzionasse come previsto, sarebbe possibile saltare completamente la parte where T : SomeBase. Il motivo per cui ne hai bisogno è che il compilatore deve conoscere tali informazioni per verificare ciò che può essere chiamato sull'oggetto fornito.

Problemi correlati