2011-04-21 12 views
15

Il metodo statico Object.Equals(Object, Object) supporta l'uguaglianza di riferimento per i tipi di riferimento e l'uguaglianza bit per i tipi di valore, dove con l'uguaglianza bitwise gli oggetti confrontati hanno lo stesso binario rappresentazione, mentre gli oggetti di uguaglianza di valore confrontati hanno lo stesso valore anche se hanno rappresentazioni binarie diverse.Ho pensato che Object.Equals (Object, Object) supporta l'uguaglianza bit a bit e non l'uguaglianza valore

Per esempio, dal momento che i1 e b1 sono di diversi tipi, non hanno la stessa rappresentazione binaria e quindi Object.Equals(Object, Object) ritorna false:

 int i1 = 100; 
     byte b1 = 100; 
     Console.WriteLine(Object.Equals(i1, b1));//false 

Object.Equals(Object, Object) dovrebbero anche restituire false quando si confrontano d1 e d2 (dal le due variabili hanno una rappresentazione binaria diversa dello stesso valore), ma restituisce invece true, il che suggerisce che le confronta con l'uguaglianza di valore:

 decimal d1 = 1.10M; 
     decimal d2 = 1.100M; 
     Console.WriteLine(Object.Equals(d1, d2)); //true 

Non dovrebbe Object.Equals(Object, Object) restituire False quando si confrontano d1 e d2?

Da http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx:

Ad esempio, consideriamo due decimale oggetti che rappresentano i numeri 1.10 e 1.1000. Gli oggetti decimali non hanno uguaglianza bit a bit poiché rappresentano rappresentazioni binarie diverse per tenere conto del diverso numero di zero finali .

thanx

+0

Questo è un bug strano che hai trovato –

risposta

1

Da MSDN:

http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx

noti che un tipo derivato potrebbe sovrascrivere il metodo Equals per implementare l'uguaglianza valore. Equality valore significa che gli oggetti confrontati hanno lo stesso valore ma diverse rappresentazioni binarie.

Decimal ha sicuramente un override uguale, come si può vedere nei metadati.

+0

Quella pagina è per il metodo Equals statico. –

+1

Il metodo statico uguale chiama l'altro. (ogni volta che entrambi gli oggetti esistono e non sono di riferimento) – Random832

+0

Per quanto posso dire, Int32.Equals, Byte.Equals e Decimal.Equals (Object) non utilizzano l'uguaglianza di valore ?! – user702769

1

Object.Equals(Object objA, Object objB) esegue innanzitutto un controllo di riferimento rapido (objA == objB). Se fallisce, prova a chiamare il virtuale Object.Equals(Object obj) che esegue l'override Decimale per fornire l'uguaglianza di valore.

+0

Per quanto ne so, Int32.Equals, Byte.Equals e Decimal.Equals (Object) non utilizzano l'uguaglianza di valore ?! – user702769

5

È possibile esaminare la sorgente di Object.Equals (oggetto, oggetto) con uno strumento come il riflettore.

Ecco il codice sorgente di Object.Equals (Object, Object):

public static bool Equals(object objA, object objB) 
{ 
    return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB))); 
} 

Esaminiamo le clausole:

(objA == objB): Questo è l'operatore di uguaglianza oggetto che controlla per vedere se questi due oggetti fare riferimento allo stesso oggetto. Questa clausola è falsa per il nostro caso.

(objA != null) && (objB != null): questo è vero per il nostro caso.

objA.Equals(objB): Questo è vero (delega al Decimal.Equals (Object))

Abbiamo tutta true sul RHS dell'operatore ||, quindi l'intera istruzione restituisce true.

+0

Int32.Equals (Object obj) restituisce true se obj è un'istanza di Int32 ed è uguale al valore di questa istanza. Se obj è di tipo byte, restituisce False. Ciò non significa che Int32.Equals (Object) utilizza il confronto bit a bit? Altrimenti, perché restituirebbe false solo perché obj è di tipo byte e non int? – user702769

+1

Probabilmente controlla i tipi. Se obj non è un'istanza di Int32, restituisce false. – ICR

+0

Controlla i tipi. Ecco Int32.Uguale (oggetto Obj), decompilato: 'public override bool Equals (oggetto obj) { if (! (Obj is int)) return false; else restituisce questo == (int) obj; } ' – MCattle

1

In nessun modo, l'uguaglianza bit a bit non ha senso e non è mai corretta. Qualunque cosa sia memorizzata in qualsiasi formato bit a bit, non ci interessa che ci preoccupiamo per il valore di business effettivo.

Per scopi aziendali o scientifici 1.10 e 1.100 sono uguali. Confronto bit a bit significa confronto lessicale, che è sbagliato. "1.10" e "1.100" sono diversi in quanto rappresentano una sequenza lessicale non corretta.

Se si desidera confrontare i bit effettivi, utilizzare BitConverter.GetBytes che fornirà una sequenza di bit effettiva.

Array.Compare( 
    BitConverter.GetBytes((decimal)1.10), 
    BitConverter.GetBytes((decimal)1.100)) 

Non so se c'è un metodo Array.Compare o no, ma è possibile crearne uno e spero tu abbia il punto.

+3

Dovresti scrivere' 1.10m' ​​invece del cast. – svick

+0

Ci sono molti casi in cui il comportamento dei tipi di 'Equals (Object)' non corrisponde a quello di altri overload di Equals né '=='. Suggerirei che 'Equals (Object)' dovrebbe rappresentare una forma di uguaglianza più rigida rispetto agli altri: dovrebbe essere "Dovrebbe essere considerato" X "come sostitutivo di" Y "". Direi che dato che '1.0m' e' 1.00m' si comportano diversamente, '1.0m.Equals ((Object) 1.00m)' dovrebbe essere falso anche se '1.0m.Equals (1.00m)' è vero, proprio come '1.0m.Equals ((Object) 1)' è falso ma '1.0m.Equals (1)' è vero. – supercat

7

Object.Equals DOVREBBE implementare l'uguaglianza di valore (non bit a bit).

Nel caso Decimale, entrambi gli oggetti sono dello stesso tipo ei valori sono uguali, quindi il risultato è true.

In int, byte case, gli oggetti sono di tipo diverso, quindi il risultato è falso.

+0

»In int, byte case, gli oggetti sono di tipo diverso, quindi il risultato è falso.« Int32.Equals (Object obj) restituisce true se obj è un'istanza di Int32 ed è uguale al valore di questa istanza. Se obj è di tipo byte, restituisce False. Non significa che Int32.Equals (Object) utilizza il confronto bit a bit? Altrimenti, perché restituirebbe false solo perché obj è di tipo byte e non int? – user702769

+2

Quasi tutti gli override di Object.Equals (x) restituiscono false se x non è del tipo corretto. In genere la prima affermazione del metodo è "if (! (X è typeof (...)) return false;" o ​​qualche variante. –

+0

Qualsiasi idea del perché sia ​​stata presa la decisione che gli stessi valori ma di tipi diversi non dovrebbero essere considerati come uguale? – user702769

9

Decimale è un tipo di valore e il metodo Equals confronta tutti i relativi campi utilizzando Reflection. Per ulteriori informazioni, si prega di fare riferimento al MSDN:

ValueType.Equals Method

Infine, il cannocchiale da MSDN è incompleta. Eccolo:

Ad esempio, consideriamo due decimali oggetti che rappresentano i numeri 1.10 e 1.1000. Gli oggetti decimali non hanno uguaglianza bit a bit poiché rappresentano rappresentazioni binarie diverse per tenere conto del diverso numero di zero finali . Tuttavia, gli oggetti hanno l'uguaglianza perché i numeri 1.10 e 1.1000 sono considerati uguali per scopi di confronto poiché gli zeri finali sono insignificanti.

Problemi correlati