2015-02-11 9 views
13

consideri il seguente esempio:Perché non posso usare la covarianza con due parametri di tipo generico?

class Base {} 

class Derived : Base {} 

class Test1 
{ 
    private List<Derived> m_X; 

    public IEnumerable<Base> GetEnumerable() 
    { 
     return m_X; 
    } 
} 

Questo compila bene, perché è IEnumerable<T>covariant in T.

Tuttavia, se faccio esattamente la stessa cosa, ma ora con i generici:

class Test2<TBase, TDerived> where TDerived : TBase 
{ 
    private List<TDerived> m_X; 

    public IEnumerable<TBase> GetEnumerable() 
    { 
     return m_X; 
    } 
} 

ottengo l'errore del compilatore

Impossibile convertire il tipo di espressione 'System.Collection.Generic.List' per restituire il tipo 'System.Collection.Generic.IEnumerable'

Cosa sto facendo di sbagliato qui?

+0

Suppongo che ci sia una spiegazione, tuttavia, usando 'return m_X.Cast ();' risolverà il tuo caso. – AgentFire

risposta

13

Il motivo è, nel primo caso, lo Base è noto per essere una classe. Nel secondo caso, il parametro type T potrebbe essere di classe o struct (come pensa il compilatore).

risolvere il caso, specificando che T è una classe, e l'errore scompare:

class Test2<TBase, TDerived> where TDerived : class, TBase 
{ 
    private List<TDerived> m_X; 

    public IEnumerable<TBase> GetEnumerable() 
    { 
     return m_X; 
    } 
} 

Così, il compilatore cerca di ci mostrano che TDerived potrebbe essere una struct (dal momento che non è stato specificato class vincolo) e as wealready know, covarianza e controvarianza non funzionano con le strutture.

+0

Perdonami la mia ignoranza dato che sono ancora abbastanza nuovo in C# (o forse questa è una di quelle cose davvero astruse su .NET in generale), ma non il fatto che 'TDerived' derivi da' TBase' - che è una classe - preclude l'ambiguità relativa al fatto che 'TDerived' sia, a sua volta, una classe o una struct? Puoi ricavare una struttura da una classe? –

+0

Interessante! Ho provato 'dove TBase: class' ma non ha avuto alcun effetto. –

+0

@roryap In C# sì, ma non necessariamente nel CLR. 'ValueType' è una classe, ma tutte le strutture derivano da essa. –

Problemi correlati