2010-07-20 11 views
16

> T > potrebbe essere dichiarato controvariante in T, poiché utilizza T solo in una posizione di input (o, equivalentemente, U essendo un sottotipo di T dovrebbe implicare che IEquatable <T> è [un sottotipo di] IEquatable <U>).Perché T IEquatable non è stato controverso in T per C# 4.0?

Quindi, perché il team BCL non lo ha annotato (per C# 4.0) con la parola chiave "in", come hanno fatto con molte altre interfacce generiche (come l'analogo IComparable)?

+0

I problemi menzionati nel filo [Qualora 'IEquatable ' '' IComparable essere implementato su rami 'sealed'?] (Http://stackoverflow.com/questions/1868316/should-iequatablet-icomparablet- essere implementato su classi non sigillate) diventerebbe molto peggio se 'IEquatable <>' fosse controverso. –

risposta

13

Penso che questo sia principalmente per una ragione filosofica piuttosto che una limitazione tecnica – in quanto è perfettamente possibile annotare semplicemente l'interfaccia. IEquatable<T> è pensato per confrontare oggetti dello stesso tipo per l'uguaglianza esatta. Un'istanza di una superclasse non è generalmente considerata uguale a un'istanza di una sottoclasse. L'uguaglianza in questo senso implica uguaglianza di tipo. Questo è leggermente diverso da IComparable<in T>. Può essere sensato definire un ordine di ordinamento relativo tra diversi tipi.

Per citare MSDN page on IEquatable<T>:

Note per gli esecutori:

sostituire il parametro tipo di interfaccia IEquatable<T> con il tipo che sta attuando questa interfaccia.

Questa frase dimostra ulteriormente il fatto che lo IEquatable<T> è progettato per funzionare tra istanze di un singolo tipo di calcestruzzo.

+0

Grazie; Sospetto che sia vicino alla verità. Sembra un peccato, però, poiché U essendo un sottotipo di T vuol dire che IEquatable T è equo per U ... non è IEquatable per U! In altre parole, non vedo nessun aspetto negativo nell'annotare l'interfaccia ... –

+0

Onestamente non vedo alcun * rialzo * per renderlo controverso. Non avrebbe senso dire che un'istanza di, per esempio, "Veicolo" è esattamente uguale a - effettivamente identica a - un'istanza di "Car". Potrebbero essere equivalenti per l'ordinamento (come con IComparable), ma non sarebbero mai veramente "uguali". –

+1

@Khalid: Considerando che un tipo di base ideale non dovrebbe essere a conoscenza dei dettagli dei suoi tipi derivati, non è in grado di decidere l'uguaglianza di questi tipi. Una classe derivata può aggiungere alcune proprietà, quindi divergendo dalla definizione di uguaglianza fornita dalla classe base. –

1

In genere i tipi ereditabili non implementano IEquatable<T>. Se IEquatable<T> includeva un metodo GetHashCode(), si poteva definire la semantica di IEquatable<T> per dire che gli articoli dovrebbero essere uguali se esaminati come T. Sfortunatamente, il fatto che IEquatable<T> sia associato allo stesso codice hash di Object.Equals significa che in generale IEquatable<T> deve implementare essenzialmente la stessa semantica di Object.Equals.

conseguenza, se un'implementazione di IEquatable<BaseClass> fa altro che chiamata Object.Equals al suo interno, una classe derivata che prevale Object.Equals e GetHashCode() e non ri-implementare IEquatable<BaseClass> finirà con un'implementazione rotto di tale interfaccia; un'implementazione di IEquatable<BaseClass> che chiama semplicemente Object.Equals funzionerà correttamente, anche in tale scenario, ma non offrirà alcun vantaggio reale rispetto a una classe che non implementa IEquatable<T>.

Dato che le classi ereditabili non dovrebbero implementare IEquatable<T> in primo luogo, la nozione di covarianza non è rilevante per le corrette implementazioni dell'interfaccia.

Problemi correlati