2010-04-28 17 views
8

Quando definiamo le nostre interfacce in C# 4.0, è possibile contrassegnare ciascuno dei parametri generici come in o out. Se proviamo a impostare un parametro generico come out e questo porterebbe a un problema, il compilatore genera un errore, non permettendoci di farlo.Inferenza covarianza e controvarianza in C# 4.0

Domanda:

Se il compilatore ha un modo di dedurre quali sono usi validi sia per covariance (out) e contravariance (in), perché dobbiamo segnare interfacce in quanto tali? Non sarebbe sufficiente limitarci a definire le interfacce come sempre, e quando abbiamo provato a usarle nel nostro codice cliente, abbiamo generato un errore se avessimo cercato di usarle in modo non sicuro?

Esempio:

interface MyInterface<out T> { 
    T abracadabra(); 
} 
//works OK 

interface MyInterface2<in T> { 
    T abracadabra(); 
} 
//compiler raises an error. 
//This makes me think that the compiler is cappable 
//of understanding what situations might generate 
//run-time problems and then prohibits them. 

Inoltre,

non è vero ciò che Java fa nella stessa situazione? Da quello che ricordo, hai fatto qualcosa come

IMyInterface<? extends whatever> myInterface; //covariance 
IMyInterface<? super whatever> myInterface2; //contravariance 

O sto mescolando le cose?

Grazie

risposta

8

Se il compilatore ha un modo di dedurre quali sono usi validi per entrambi covarianza (out) e controvarianza (in), perché dobbiamo segnare interfacce in quanto tali?

Non sono sicuro di aver capito la domanda. Penso che tu stia chiedendo due cose.

1) Il compilatore può dedurre le annotazioni della varianza?

e

2) Perché C# non supporta varianza call-site come Java fa?

La risposta alla prima è:

interface IRezrov<V, W> 
{ 
    IRezrov<V, W> Rezrov(IRezrov<W, V> x); 
} 

vi invito a tentare di dedurre ciò che tutti i possibili annotazioni di varianza legali sono su V e W. Si potrebbe ottenere una sorpresa.

Se non riesci a trovare un'annotazione di varianza migliore per questo metodo, perché pensi che possa farlo il compilatore?

Ulteriori motivi qui:

http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

Più in generale: la tua domanda indica ragionamento fallace. La possibilità di controllare a buon mercato se una soluzione è corretta non implica logicamente che vi sia un modo economico per trovare una soluzione corretta. Ad esempio, un computer può facilmente verificare se p * q == r è vero o falso per i numeri primi di due cifre p e q. Ciò non implica che sia facile prendere r e trovare p e q tale che l'uguaglianza sia soddisfatta.Il compilatore può facilmente verificare se un'annotazione della varianza è corretta o errata; ciò non significa che possa trovare un'annotazione di varianza corretta tra i potenzialmente miliardi di possibili annotazioni.

La risposta al secondo è: C# non è Java.

+0

Penso che la sua seconda domanda fosse più simile a "In che modo le annotazioni sulla varianza di C# sono diverse dai caratteri jolly di Java?" – Gabe

+1

@Gabe: C# presenta * varianza * dichiarazione-sito *. Java ha * varianza * call-site *. Chiamare la varianza del sito è un'idea interessante per essere sicuro, ma mi sembra strano avere un tipo di variante basato su come viene utilizzato in un particolare sito, al contrario di come è definito comportarsi. –

+0

Sì, ora capisco qual è il problema con l'utilizzo di Java. Ha il vantaggio di non dover dichiarare i parametri dell'interfaccia come dentro o fuori, ma in questo caso alcuni client potrebbero dargli qualche utilità in questo momento che in seguito potrebbe non essere protetto se ho intenzione di aggiornare la mia interfaccia. –

0

OK, qui è la risposta a quello che ho chiesto (dalla risposta di Eric): http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

In primo luogo, mi sembra che la varianza dovrebbe essere qualcosa che si deliberatamente progettare nella vostra interfaccia o delegare. Rendendolo solo inizia a verificarsi senza alcun controllo da parte dell'utente che lavora contro quell'obiettivo, e anche può introdurre cambiamenti di rottura. (Ulteriori su quelle in un post successivo!)

Ciò significa anche che automagicamente come il processo di sviluppo va avanti e metodi vengono aggiunti alle interfacce, la varianza dell'interfaccia può cambiare inaspettatamente. Questo potrebbe introdurre modifiche impreviste e di vasta portata altrove nel programma.

Ho deciso di metterlo esplicitamente qui perché anche se il suo link ha la risposta alla mia domanda, il post stesso non lo fa.

Problemi correlati