waarom werken gelijken niet hetzelfde wanneer items naar een object worden gecast?

wanneer ik int en zweef om te protesteren en te vergelijken, is de gelijkheid altijd fout. Waarom?

        float f = 0.0f;
        int i = 0;
        Console.WriteLine(f.Equals(i));//true
        Console.WriteLine(i.Equals(f));//false
        Console.WriteLine(i == f);//true
        Console.WriteLine("----------------");
        object obf = f;
        object obi = i;
        Console.WriteLine(obf.Equals(obi));//false
        Console.WriteLine(obi.Equals(obf));//false
        Console.WriteLine(obi == obf);//false
        Console.WriteLine("----------------");

Bijwerken: dit is NIET het geval voor hetzelfde type

        int i1 = 1;
        int i2 = 1;
        object oi1 = i1;
        object oi2 = i2;
        Console.WriteLine(oi1.Equals(oi2));//true
        Console.WriteLine(oi2.Equals(oi1));//true
6

8 antwoord

Een float is alleen gelijk aan een andere float en een int is alleen gelijk aan een andere int . De enige regels die true retourneren zijn deze:

Console.WriteLine(f.Equals(i));
Console.WriteLine(i == f);

In beide gevallen is er een impliciete conversie van de waarde van i in float , dus ze zijn gelijk aan:

Console.WriteLine(f.Equals((float) i));
Console.WriteLine((float) i == f);

Deze conversies zijn slechts normale conversies die nodig zijn voor de overbelastingsresolutie van methoden en operators.

Geen van de rest van de regels heeft betrekking op die impliciete conversie, dus vergelijken ze de twee verschillende typen, wat een resultaat van false oplevert, zelfs als het is door te vergelijken met de waarde ( wat het geval is met alle is gelijk aan oproepen). Dat is de reden waarom het gebruik van Gelijk aan op de ingevoegde int waarden retourneert true , omdat dat twee waarden van hetzelfde type vergelijkt , op waarde .

In dit geval:

Console.WriteLine(obi == obf);

het is niet eens proberen om numerieke waarden te vergelijken - het is het vergelijken van de referenties voor de ingesloten objecten. Omdat er twee verschillende referenties zijn, is het resultaat false - en zou het zelfs zijn als beide waarden van het type int zouden zijn.

10
toegevoegd
@CharlesLambert: Ja. Bekijk de IL en je zult zien dat het wordt uitgevoerd.
toegevoegd de auteur Jon Skeet, de bron
wordt de impliciete conversie afgehandeld bij het compileren?
toegevoegd de auteur Charles Lambert, de bron

Anderen hebben al uitgelegd waarom == niet werkt zoals verwacht op uw objecten.

Wat betreft uw bewerking: oi1.Equals (oi2) werkt omdat is gelijk aan is een virtuele functie en dus Int32.Equals (object) wordt aangeroepen, waarvan de geretourneerde waarde als volgt is gedefinieerd:

true als obj een instantie is van Int32 en gelijk is aan de waarde van deze instantie; anders false .

Dit verklaart ook waarom obi.Equals (obf)) false retourneert: obf is geen instantie van Int32.

3
toegevoegd

Je bokst de int en zweeft naar een object, wat betekent dat ze worden vergeleken als referenties. Omdat ze geen verwijzingen zijn naar hetzelfde object, zijn ze niet gelijk.

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

1
toegevoegd

Wanneer u twee objecten hebt verklaard, verwijst dit naar een andere geheugenlocatie:

object obf = f;        //this simplified as new float(f)
object obi = i;        //this simplified as new int(i)

maar probeer het volgende, laat het ene object verwijzen naar een ander:

obf = obi;
Console.WriteLine(obf.Equals(obi));

MSDN, Object.Equals Method

De standaardimplementatie van Equals ondersteunt referentiegelijkheid voor   referentietypen en bitsgewijze gelijkheid voor waardetypen. Referentie   gelijkheid betekent dat de objectreferenties die worden vergeleken verwijzen naar de   hetzelfde object. Bitwise gelijkheid betekent dat de objecten die worden vergeleken hebben   dezelfde binaire representatie.

1
toegevoegd

Om meer te weten te komen over wat er gebeurt als je waardetypen invoert, beschrijft Shivprasad dit hier heel bondig:

Boksen en unboxen

Omdat je de waardetypes voor objecten in dozen doet, voer je nu vergelijkingsgelijkheid uit. Omdat ze nu op verschillende geheugenlocaties in uw voorbeeld staan, wordt false geretourneerd.

1
toegevoegd

Omdat Gelijk aan het adres van de objectreferentie vergelijkt en de twee getallen op verschillende locaties worden opgeslagen. als u de twee waardetypen vergelijkt, gedraagt ​​Equals zich correct omdat het is overschreven voor float, int, string en andere typen.

0
toegevoegd

Omdat ze zijn toegewezen aan verschillende memeory cellen. 2 objecten zijn = alleen als ze hetzelfde object zijn. In de float en int deel krijgt u een waar wanneer u de 2 variabelen test omdat de looptijd hun waarde controleert. dat is alles!

0
toegevoegd

Wanneer u een waardetype naar een object cast, wordt het feitelijk in de heap geplaatst en vergelijkt == de referenties op dat punt, wat onwaar is. (Vereenvoudigd)

0
toegevoegd