Domanda

Perché, con un vincolo generico sul parametro di tipo T della classe P di " deve ereditare da A " ;, la prima chiamata ha esito positivo ma la seconda chiamata fallisce con l'errore di conversione del tipo dettagliato nella commento:

abstract class A { }

static class S
{
    public static void DoFirst(A argument) { }
    public static void DoSecond(ICollection<A> argument) { }
}

static class P<T>
    where T : A, new()
{
    static void Do()
    {
        S.DoFirst(new T());             // this call is OK

        S.DoSecond(new List<T>());      // this call won't compile with:

        /* cannot convert from 'System.Collections.Generic.List<T>'
           to 'System.Collections.Generic.ICollection<A>' */
    }
}

Il vincolo generico non dovrebbe garantire che List<T> sia effettivamente ICollection<A>?

È stato utile?

Soluzione

Questo è un esempio della mancanza di C # di covariance su tipi generici (C # supporta la covarianza dell'array). C # 4 aggiungerà questa funzione sui tipi di interfaccia e aggiornerà anche diversi tipi di interfaccia BCL per supportarla.

Vedi C # 4.0: Covariance e controvarianza :

  

In questo articolo I & # 8217; cercherò di coprirne uno   delle innovazioni di C # 4.0. Uno di   nuove funzionalità è covarianza e   contraddizione su parametri di tipo che   è ora supportato da delegati generici   e interfacce generiche. Prima lascia & # 8217; s   vedi cosa significano queste parole :)

Altri suggerimenti

Il vincolo non ha alcun effetto sul problema; il problema è che stai passando un Elenco in un parametro che richiede ICollection - C # non supporta la covarianza, quindi devi trasmettere esplicitamente l'elenco a un ICollection:

S.DoSecond((ICollection<A>) new List<T>());      // this call will be happy

Hai digitato fortemente il parametro per DoSecond come tipo ICollection < A > ;. Nonostante il fatto che T sia di tipo A, al momento della compilazione non esiste alcun implicito cast tra List & Lt; T & Gt; e ICollection < A > ;. Dovrai creare l'elenco e lanciarlo su ICollection & Lt; A & Gt; quando chiami DoSecond o fai di DoSecond un metodo generico stesso.

NOTA: questo tipo di cast implicito dovrebbe essere supportato in C # 4.0, che fornirà una migliore co / contraddizione rispetto a ciò che offre C # 3.0.

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