2010-03-29 21 views
18

Qual è il motivo reale per tale limite? È solo un lavoro da fare? Concettualmente è difficile? È impossibile?Perché C# (4.0) non consente la co- e controvarianza nei tipi di classi generiche?

Certo, non è possibile utilizzare i parametri di tipo nei campi, perché sono sempre in lettura e scrittura. Ma quella non può essere la risposta, vero?

Il motivo di questa domanda è che sto scrivendo un articolo sul supporto delle varianze in C# 4, e sento che dovrei spiegare perché è limitato ai delegati e alle interfacce. Giusto per invertire l'onere della prova.

Aggiornamento: Eric ha chiesto un esempio.

Che dire di questo (non so se questo ha un senso, ma :-))

public class Lookup<out T> where T : Animal { 
    public T Find(string name) { 
    Animal a = _cache.FindAnimalByName(name); 
    return a as T; 
    } 
} 

var findReptiles = new Lookup<Reptile>(); 
Lookup<Animal> findAnimals = findReptiles; 

La ragione per avere che in una classe potrebbe essere la cache che si tiene nella classe stessa. E per favore non nominare i tuoi diversi tipi di animali domestici uguali!

BTW, questo mi porta a optional type parameters in C# 5.0 :-)

Update 2: Non sto sostenendo il CLR e C# dovrebbe consentire questo. Sto solo cercando di capire cosa ha portato a ciò che non funziona.

+1

Certo, questo è un esempio ragionevole ma non hai mostrato nulla che non possa essere fatto anche con le interfacce. Basta creare l'interfaccia ILookup e cercare l'applicazione . Quale avvincente vantaggio aggiuntivo sulla varianza dell'interfaccia lo scenario per la varianza di classe si aggiunge? –

+1

Nessuno, in realtà. Oltre a ciò è meno codice. Fatemi inverso l'onere della prova. Come potremmo spiegare perché non è supportato. Non sto chiedendo di implementarlo, in realtà. "È sempre stato così" non conta! :-) –

+0

Non è necessario fornire una giustificazione per * non * l'implementazione di una funzione. Non implementare una funzionalità è * gratuito *. Piuttosto, dobbiamo fornire una giustificazione per l'implementazione di una funzionalità: le funzionalità possono costare milioni di dollari a Microsoft e imporre un onere ancora maggiore ai nostri clienti che devono quindi spendere tempo e denaro per apprendere la funzionalità. –

risposta

18

Prima di tutto, come dice Tomas, che non è supportata nel CLR.

In secondo luogo, come funzionerebbe? Supponiamo di avere

class C<out T> 
{ ... how are you planning on using T in here? ... } 

T può essere utilizzato solo nelle posizioni di uscita. Come si nota, la classe non può avere alcun campo di tipo T perché il campo potrebbe essere scritto. La classe non può avere metodi che accettano una T, perché quelli sono logicamente scritti. Supponiamo che tu abbia questa caratteristica - come ne approfitteresti?

Questo sarebbe utile per classi immutabili se potessimo, diciamo, rendere legale avere un campo di sola lettura di tipo T; in questo modo ridurremmo in maniera massiccia la probabilità che fosse scritto in modo improprio. Ma è abbastanza difficile trovare altri scenari che consentano la varianza in modo tipicamente sicuro.

Se si dispone di uno scenario del genere, mi piacerebbe vederlo. Sarebbe un punto in cui un giorno potrebbe essere implementato nel CLR.

UPDATE: Vedere

Why isn't there generic variance for classes in C# 4.0?

per più su questa questione.

+1

Buona domanda :) Ricordo una discussione tra Anders e qualche geek del compilatore Java (spiacente) al Lang.NET l'anno scorso, dove il ragazzo Java chiesto questa funzione. Sembrava sapere perché l'ha chiesto. Ma non riesco a ricordare. Pensavo alle classi senza stato.Proverò a inventare qualcosa nella domanda. –

+1

Questa sarebbe sicuramente una caratteristica interessante per tipi di dati immutabili come 'Tuple ', ma sono d'accordo che questo non è abbastanza convincente per cambiare il CLR :-). –

+3

Un altro caso d'uso è un tipo fantasma in cui la T viene utilizzata solo per la sicurezza del tipo e non per l'implementazione della classe. – porges

8

Per quanto ne so, questa funzione non è supportata da CLR, quindi l'aggiunta di questo richiederebbe un lavoro significativo anche sul lato CLR. Credo che la co- e contro-varianza per interfacce e delegati fosse effettivamente supportata su CLR prima della versione 4.0, quindi questa era un'estensione relativamente semplice da implementare.

(implementazione di questa funzione per le classi sarebbe sicuramente utile, però!)

+0

Hai ragione. La varianza nei parametri di tipo generico di interfacce e delegati arrivava con CLR 2.0 - non proprio in C# –

1

Se fossero consentiti, è possibile definire classi o strutture utili al 100% sicure per tipo (senza tipografie interne) che erano covarianti rispetto al loro tipo T, se il loro costruttore accettava uno o più fornitori T o T. Potrebbero essere definite classi o strutture utili al 100% sicure che erano controvarianti rispetto a T se i loro costruttori accettavano uno o più consumatori T. Non sono sicuro che ci sia molto vantaggio di una classe su un'interfaccia, oltre alla possibilità di usare "nuovo" piuttosto che usare un metodo statico di fabbrica (molto probabilmente da una classe il cui nome è simile a quello dell'interfaccia), ma posso certamente vedere casi d'uso per avere strutture immutabili supportano la covarianza.

Problemi correlati