2011-06-03 14 views
5

Ho letto la seguente dichiarazione relativa al confronto dei tipi di valore C# in C# in Depth, Second Edition più volte.Confronti diretti di tipi di valore C#

pagina 77,

Quando un parametro tipo è vincolata (vincoli vengono applicati ad esso), è possibile utilizzare == e! = Operatori, ma solo per confrontare un valore di quel tipo con null. Non è possibile confrontare due valori di tipo T l'uno con l'altro.

...

Quando un parametro di tipo è costretto a essere un tipo di valore, == e! = Non può essere utilizzato con esso a tutti.

Se ho capito (io non la penso così) in modo corretto, fondamentalmente mi dice che non si può uso == o! = Per confrontare due tipi di valore. Perché perché perché?

Sarà meglio se un esempio semplice può essere dato per questo caso. Qualcuno può darmi una piccola idea di ciò che il paragrafo precedente cerca di trasmettere?

+2

Sospetto che ciò eviti confusione con l'overloading dell'operatore, poiché un operatore == sovraccarico non verrebbe utilizzato quando il parametro di tipo generico è un tipo di valore. È possibile utilizzare Object.Equals, tuttavia, quali implementano i tipi di valore ben educati e che avranno lo stesso comportamento di == (per i tipi ben educati). –

+1

@Dan Bryant, non è solo per evitare confusione. Non c'è alcuna garanzia che un tipo di valore supporti gli operatori == e! =, E noi * non possiamo usare l'implementazione System.Object per i tipi di valore, perché il test dell'eguaglianza di riferimento funziona solo su istanze in box. * Bene, potremmo in teoria specificare che gli operandi siano inscatolati per utilizzare il controllo di uguaglianza di riferimento, ma in tal caso l'espressione sarebbe sempre falsa, il che è chiaramente inutile. – phoog

+0

@phoog, lo 'Object.Equals' statico chiamerà effettivamente l'implementazione Equals dell'oggetto (anche se è un tipo di valore in box), quindi è un modo valido per confrontare i tipi di valore pari. Gestisce anche il confronto di null con i tipi di valore. 'Object.ReferenceEquals' costringe esplicitamente il controllo a essere per l'uguaglianza di riferimento, che può essere utile nei casi in cui un tipo di riferimento sovrascrive l'operatore di uguaglianza, ma ha un bug per il caso di confronto nullo (ho incontrato questo prima con un terzo- API party.) –

risposta

7

Significa semplicemente questo quando vincolare un tipo di valore (secondo paragrafo)

static bool TryToCompare<T>(T first, T second) where T : struct 
{ 
    return first == second; // not legal 
    return first.Equals(second); // legal 
} 

Senza il vincolo valore tipo sul generico, dice anche questo (primo paragrafo)

static bool TryToCompare<T>(T first, T second) 
{ 
    return first == second; // not legal 
    return first == null; // legal 
    return first.Equals(second); // legal 
} 

Se si vincola T a un tipo di riferimento, è possibile ottenere utilizzando ==

static bool TryToCompare<T>(T first, T second) where T : class 
{ 
    return first == second; // legal 
    return first == null; // legal 
    return first.Equals(second); // legal 
} 
+0

il primo esempio sulla tua seconda funzione fallisce b/c non abbiamo alcun vincolo su T e T può essere struct o class. È corretto? -thx – q0987

+1

Più o meno. Non vi è alcuna garanzia che un tipo di valore "T" definisca l'operatore "==". Per ulteriori informazioni su questo argomento, ti suggerirei di vedere questa domanda e la risposta più importante: http://stackoverflow.com/questions/5808057/operator-cant-be-applied-to-type-t –

+0

+1: in pratica ho solo usa '==' e '! =' contro le costanti. Se non sbaglio, puoi anche usare 'default (T)' per la valutazione. Altrimenti, io uso 'Equals()'. – IAbstract

0

Gli oggetti non sono confrontabili poiché un confronto usando == sta verificando se il riferimento è lo stesso (l'indirizzo di memoria). Normalmente si userebbe se (string1.Equals (stringa2)).

Qualcosa che non capisco è che ho visto circostanze in cui == funziona con stringhe e circostanze in cui non lo fa.

+0

Da un risultato POV, '==' e 'stringa1.Equals (stringa2)' non dovrebbe essere diverso. Sono calcolati in modi diversi, ma per le stringhe corte, 'Equals' ha un leggero vantaggio di velocità. Buon articolo qui: http://www.dotnetperls.com/string-equals – keyboardP

+0

Sulle stringhe, si iniziano a vedere risultati "imprevisti" quando vengono effettuati confronti con gli oggetti stringa * as *. Si consideri 'string x =" ONE "; string y = string.Format ("ON {0}", "E"); bool b = x == y; bool c = (oggetto) x == (oggetto) y; '' b' sarà vero, 'c' sarà falso. Tuttavia, cambia 'y' per essere' string y = "ONE"; ', e ora' c' sarà anche vero. –

+0

Se il riferimento a uno degli operandi stringa ha un tipo di oggetto in fase di compilazione, allora == verrà compilato per un controllo di uguaglianza di riferimento. Se sono entrambi riferimenti a stringhe, otterrai l'implementazione della stringa dell'operatore. – phoog