2013-02-14 11 views
18

Lo System.Linq.ILookUp definizione recitaNon dovrebbe ILookup <TKey, TElement> essere (dichiarato) covariante in TElement?

interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable { 
    int Count { 
     get; 
    } 

    IEnumerable<TElement> this[TKey key] { 
     get; 
    } 

    bool Contains(TKey key); 
} 

Poiché IEnumerable è covariante in IGrouping < TKey, TElement >, IGrouping < TKey, TElement > è covariante TElement e l'interfaccia espone solo TElement come un tipo di ritorno, Suppongo che ILookup sia anche covariante in TElement. Infatti, la definizione

interface IMyLookup<TKey, out TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable { 
    int Count { 
     get; 
    } 

    IEnumerable<TElement> this[TKey key] { 
     get; 
    } 

    bool Contains(TKey key); 
} 

compila senza problemi.

Quindi, quale potrebbe essere il motivo per cui la parola chiave out manca nella definizione originale? Potrebbe essere aggiunto le versioni future di Linq?

+1

... nessuno ha pensato, progettato, implementato, testato, rilasciato .... o forse una ragione completamente diversa. –

+0

Beh, mi stavo chiedendo se è già tutta la storia. D'altra parte, sono curioso di sapere se tali casi sono a) b) probabile che sia _fixed_ in futuro – bigge

+0

LINQ è stato introdotto in .NET Framework 3.5 (C# 3.0), mentre la varianza per i parametri di tipo generico nelle interfacce da C# 4.0 . Potrebbe essere questa la ragione? –

risposta

7

Tracciare la documentazione MSDN, Covariance and Contravariance in Generics sono stati introdotti in .NET Framework 4 In precedenza, c'era il IEnumerable<T> da .NET Framework 2.0 fino a .NET Framework 3.5. Quindi in .NET Framework 4.0 è possibile vedere IEnumerable<out T> con il parametro di tipo T come covarianza.

IGrouping<TKey, TElement> e ILookup<TKey, TElement> esistono da quando .NET Framework 3.5. In .NET Framework 4.0 il primo è stato aggiornato a IGrouping<out TKey, out TElement> ma quest'ultimo è stato omesso senza specificare il motivo.

TKey non può essere covariante in quanto le implementazioni di Contains(TKey) e this[TKey] impediscono che.

Riguardo a TElement, il problema non è chiaro. Non credo che i designer lo abbiano mancato. Forse la causa sta nei piani per il futuro. O volevano impedire che qualcosa di simile al di sotto, ma io non so perché:

string[] strings = new[] {"a", "a", "b", "b", "b", "c"}; 
ILookup<string, string> lookup = strings.ToLookup(s => s); // Valid. 
ILookup<string, object> lookup = strings.ToLookup(s => s); // Now invalid, but would correct if TElement was covariant (out TElement). 

ci sono anche altri autori, che prestare attenzione a tale questione:

ToLookup:

Un punto un po 'strano da notare è che mentre IGrouping è covariante in TKey e TElement, ILookup è invariato in entrambi i suoi parametri di tipo. Mentre TKey deve essere invariato, è ragionevole che TElement sia covariante

+0

Davvero una bella risposta, grazie. Anche se questo non risponde direttamente alla mia domanda, la tua risposta mostra che c'è un problema qui (anche se solo un piccolo). Ho accettato la tua risposta dal momento che probabilmente è tutto quello che si può scoprire sul problema. +1 per trovare la citazione. – bigge

+0

@bigge: Grazie per aver apprezzato il mio tempo. Avevo in mente il caso. Se trovo qualcosa di nuovo, lo aggiungerò alla risposta. –

+0

Quando si dice "prevenire qualcosa come il seguito", cosa intendi? Si specifica che entrambe le chiamate 'ToLookup' sono legali (una" OK "e una" Legal "). Qual è il problema se tutto funziona? –

Problemi correlati