Domanda

Ci sono alcuni posti già su Stack Overflow su questo genere di cose, ma non esattamente la stessa - in modo scuse in anticipo se si tratta di qualcosa che è già stato risposto

.

Perché questo non funziona:

public class MyBase { }

public class MyUtils
{
    public bool Foo<T> (T myObject) { return true; }
    public bool Foo (MyBase myBaseObject) { return false; }

    public void Go<T> (IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            // this test fails
            Assert.IsFalse (Foo (item));
        }
    }
}

Se io chiamo Go () di cui sopra e passare un carico di oggetti MyBase, ogni chiamata a Foo Foo chiamerà la generica (), che restituisce il valore true.

new MyUtils ().Go (new MyBase[] { new MyBase (), new MyBase () });      

Perché non chiamare la versione MyBase specializzata invece? Se chiamo Foo (nuova MyBase ()) direttamente, si deduce che correttamente chiamata a fare. È questo a causa della mancanza di covarianza per le collezioni in C # 3, o sono solo di essere stupido e non fare questo correttamente?

Grazie!

Isaac

È stato utile?

Soluzione

E non chiama il "specializzata" uno perché il compilatore sceglie il metodo da chiamare quando il programma (che in questo caso, è la funzione Go) è compilato , non quando viene eseguito.

Quando il compilatore è la compilazione della funzione Go, l'unica informazione che ha è che ci sia qualche oggetto di tipo T. Non ha alcuna idea che si può ad un certo punto più avanti nel tempo gli mette a disposizione un oggetto di tipo MyBase. L'unica opzione che ha è di scegliere il sovraccarico di Foo<T>, e così si cuoce che per il programma compilato.

Se si desidera un'applicazione di scegliere sovraccarichi in fase di esecuzione, e scegliere il migliore di sovraccarico, cercando in oggetto, mentre l'applicazione è in esecuzione, che si chiama "la spedizione dinamica", e viene utilizzato solo per i linguaggi dinamici come Ruby, Python, PHP, ecc

C # 3 è completamente statico e non supporta questa. Dovreste scrivere un if-statement nel codice per verificare il tipo se si voleva lavorare in questo modo. C # 4 d'altra parte, ha qualche supporto dinamico. Se si stesse scrivendo questo codice in C # 4, si potrebbe dichiarare la funzione 'Go' nel seguente modo:

 public void Go<T> (IEnumerable<dynamic> items)

Poi si userebbe la spedizione dinamica a tempo di esecuzione di scegliere quale sovraffaticamento chiama, e avrebbe chiamato il sovraccarico specializzato di prendere MyBase

Altri suggerimenti

Secondo le specifiche C # (7.4.3.2), il metodo non generico è migliore di quella generica, quindi dovrebbe essere selezionato.

Ma, penso che quella generica viene prelevato nel tuo caso, perché è chiamato in un contesto invocazione generica (il "foreach" loop).

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