Come dice il titolo: devo sostituire l'operatore ==
? che ne dici del metodo .Equals()
? Qualcosa che mi manca?Cosa deve essere sovrascritto in una struttura per garantire che l'uguaglianza funzioni correttamente?
risposta
Un esempio da MSDN
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return re.GetHashCode()^im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
Per i curiosi: http://msdn.microsoft.com/en-us/library/336aedhh(v=VS.71).aspx – Mike
Mi chiedo se non sarebbe meglio per le prestazioni usare 'Complesso altro = obj come Complesso' e poi controlla se 'altro == null' invece di usare' is' e poi un cast ... –
@Clement: non puoi farlo per una struttura; il risultato non può essere nullo. Avresti un errore di compilazione. –
La differenza fondamentale tra i due è che l'operatore ==
è statico, cioè il metodo appropriato per invocare viene determinata in fase di compilazione, mentre il metodo Equals
viene richiamato dinamicamente su un esempio.
Definire entrambi è probabilmente la cosa migliore da fare, anche se ciò è meno importante nel caso delle strutture, poiché le strutture non possono essere estese (una struct non può ereditare da un'altra).
È inoltre necessario implementare IEquatable < T>. Ecco un estratto da Linee guida per la progettazione di framework:
DO implement IEquatable su tipi di valore. Il metodo Object.Equals sui tipi di valore causa la boxe e la sua implementazione predefinita non è molto efficiente perché utilizza il refection. IEquatable.Equals può offrire prestazioni molto migliori e può essere implementato in modo che non provochi il pugilato.
public struct Int32 : IEquatable<Int32> {
public bool Equals(Int32 other){ ... }
}
seguono le stesse linee guida per imperativi Object.Equals quando IEquatable.Equals di attuazione. Vedere la sezione 8.7.1 per dettagliate linee guida su imperativi Object.Equals
Quindi questo è usato solo sui tipi di valore? (non si fa riferimento?) – UpTheCreek
Poiché i tipi di riferimento non devono essere racchiusi tra loro quando vengono trasmessi come oggetto, ergo, IEquatable
Unfortunetely Non ho abbastanza fama di commentare altre voci. Quindi sto postando un possibile miglioramento per la soluzione migliore qui.
Correggetemi, se sbaglio, ma l'attuazione di cui sopra
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return re.GetHashCode()^im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
Ha difetto principale. Sto riferendosi a
public override int GetHashCode()
{
return re.GetHashCode()^im.GetHashCode();
}
XOR è simmetrico, così complesso (2,1) e Complex (1,2) darebbe stesso hashCode.
probabilmente dovremmo fare qualcosa di più simile a:
public override int GetHashCode()
{
return re.GetHashCode() * 17^im.GetHashCode();
}
Avere collisioni hashcode non è necessariamente un problema. In effetti avrai sempre la possibilità di una collisione (leggi su buchi di pigione/paradosso di compleanno) Nel tuo caso Complesso (1,4) e Complesso (4,1) collidono (sicuramente ci sono state meno collisioni) dipende dai tuoi dati . Il codice hash viene utilizzato per estirpare rapidamente il 99,999% degli oggetti indesiderati (ad esempio, in un dizionario) Gli operatori di uguaglianza hanno l'ultima parola. – DarcyThomas
È stato detto che più proprietà hai sulla struttura, c'è una maggiore possibilità di collisione. Questo potrebbe essere un algoritmo di hash migliore: http://stackoverflow.com/a/263416/309634 – DarcyThomas
Solo per completezza vorrei anche consigliare al sovraccarico Equals
metodo:
public bool Equals(Complex other)
{
return other.re == re && other.im == im;
}
questo è un vero e proprio miglioramento spead come non c'è verificano boxe dell'argomento di input del metodo Equals(Object obj)
Alcune best practice per l'utilizzo dei tipi di valore:
- renderli immutabili
- Override Equals (quello che prende un oggetto come argomento);
- overload È uguale a prendere un'altra istanza dello stesso tipo di valore (ad esempio * Equals (Complex other));
- operatori di sovraccarico == e! =;
- esclusione GetHashCode
Questo deriva da questo post: http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/
maggior parte del tempo si può evitare Equals e GetHashCode di esecuzione le strutture - perché non v'è un'implementazione automatica dal compilatore per i tipi di valore utilizzando bit a bit contenuto + riflessione per i membri di riferimento.
Dai un'occhiata alla quel post:! Which is best for data store Struct/Classes?
Così, per la facilità d'uso si potrebbe ancora implementare == e =.
Ma la maggior parte delle volte è possibile evitare l'implementazione di Equals e GetHashcode.
Un caso in cui è necessario implementare Equals e GetHashCode è per un campo che non si vuole prendere in considerazione.
Ad esempio un campo che varia con il passare del tempo come Age of a Person o instantSpeed di un'auto (l'identità dell'oggetto non dovrebbe cambiare se si desidera ritrovarla nel dizionario nello stesso posto)
Cordiali saluti, codice migliore
- 1. Cosa deve fare un sito web che deve essere scalato?
- 2. setProperty deve essere sovrascritto da tutte le sottoclassi di SOAPMessage
- 3. E 'possibile in Python dichiarare che il metodo deve essere sovrascritto?
- 4. Cosa deve essere inserito nell'assembleaTrademarkAttribute?
- 5. cosa deve essere implementato da una classe astratta in java?
- 6. Esiste un esempio per cui Equals/GetHashCode deve essere sovrascritto in NHibernate?
- 7. Che cosa significa "operatore = deve essere un membro non statico"?
- 8. WebView deve essere caricato due volte per caricare correttamente
- 9. Cosa deve essere passato in if() per stampare 'Hello World'?
- 10. Cosa deve essere restituito dall'API per i comandi CQRS?
- 11. Come utilizzare correttamente fget in una struttura?
- 12. Struttura directory EXTJS: cosa può essere cancellato?
- 13. Cosa deve essere passato per il parametro @object di BeginInvoke?
- 14. Che cosa significa "la scelta deve essere coerente per tutti i consumatori"?
- 15. Come funziona esattamente il subDAG in Airflow? Che cosa significa che un subDAG deve essere abilitato?
- 16. Che cosa significa "Il file binario dwarfdump deve esistere e deve essere eseguibile"?
- 17. Che cosa dovrei considerare per garantire una porta trasparente delle mie app per iPhone su iPad?
- 18. Il fieldset deve essere in una forma?
- 19. Perché il codice C++ deve essere contenuto all'interno delle funzioni?
- 20. Come Avvertenze Button che deve essere fissato
- 21. Che cosa significa per una funzione hash essere incrementale?
- 22. Che cosa dovrebbe essere usato per verificare l'identità in C++?
- 23. Che cosa significa che un punto di interruzione deve essere installato?
- 24. perché la dimensione della struttura deve essere un multiplo dell'allineamento più grande di qualsiasi membro della struttura
- 25. È un esecutore che deve essere riutilizzato?
- 26. Che cosa deve fare effettivamente OOttimizeForNetworkUse?
- 27. Anche il Salt per una password Hash deve essere "hash"?
- 28. Come posso specificare che Intellitest deve essere utilizzato per un'interfaccia?
- 29. Cosa deve essere racchiuso tra istruzioni then() in CasperJS? Come determinare l'ordine di esecuzione delle funzioni di sincronizzazione/asincrono?
- 30. Valore 'e' può essere sovrascritto in IE 8 e precedenti
Guarda anche http://stackoverflow.com/questions/1972262/c-sharp-okay-with-comparing-value-types-to-null/21962298 - se non lo sei attento quindi il confronto della tua struct (un tipo di valore) a null si compila bene ma non fa quello che ti aspetti. – yoyo