öğeler nesneye dökülürken neden eşit çalışmaz?

Ben int ve float ve ben onları karşılaştırmak için eşitlik ve eşitlik her zaman yanlıştır. Niye ya?

        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("----------------");

Güncelleştirme: aynı tip için durum böyle değil

        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 cevap

Bir float sadece başka bir float 'a eşittir ve bir int sadece başka bir int ' ye eşittir. true döndüren tek satırlar şunlar:

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

Her iki durumda da, i değerinin float değerine örtülü bir dönüşümü vardır, yani şunlara eşdeğerdir:

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

Bu dönüşümler, yöntemlerin ve operatörlerin aşırı yüklenmesi için gereken normal dönüşümlerdir.

Çizgilerin geri kalanının hiçbiri bu örtük dönüşümü içermez. Bu nedenle, iki farklı türü karşılaştırırlar. Bu, değerine göre karşılaştığında bile false sonucunu verir ( tüm Eşittir çağrıları ile durum böyle). Bu nedenle, aynı türden iki değeri karşılaştırdığından kutulu int değerler true Equals kullanılmalıdır. , değere göre .

Bu durumda:

Console.WriteLine(obi == obf);

sayısal değerleri karşılaştırmaya bile çalışmıyor - kutulu nesneler için referanslar ile karşılaştırılıyor. İki farklı referans olduğundan, sonuç false - olur ve her iki değer de int türünde olsa bile olur.

10
katma
@CharlesLambert: Evet. IL'ye bir göz atın ve gerçekleştirildiğini göreceksiniz.
katma yazar Jon Skeet, kaynak
örtülü dönüşüm derleme zamanında ele alınır mı?
katma yazar Charles Lambert, kaynak

Diğerleri, == neden nesnelerinizde beklendiği gibi çalışmadığını zaten açıkladı.

Düzenlemenizle ilgili olarak: oi1.Equals (oi2) , Equals sanal bir işlev olduğu için çalışır ve bu nedenle, Int32.Equals (object) denir, dönüş değeri aşağıdaki gibi tanımlanır:

<1> eğer nesne bir Int32 örneğiyse ve bu örneğin değerine eşitse

true ; aksi halde, false .

Bu ayrıca obi.Equals (obf)) 'in neden false değerini döndürdüğünü de açıklar: obf , Int32'nin bir örneği değildir.

3
katma

Bir nesneyi kutlar ve bir nesneye süzülürsünüz, yani referans olarak karşılaştırıldıkları anlamına gelir. Aynı nesneye referans olmadıkları için eşit değiller.

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

1
katma

İki nesne bildirdiğinizde, farklı bir bellek konumuna başvururlar:

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

ama aşağıdakileri deneyin, bir nesnenin diğerine referans vermesine izin verin:

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

MSDN, Object.Equals Method

Eşittir varsayılan uygulama için referans eşitliği destekler   Referans türleri ve değer türleri için bitsel eşitlik. Referans   Eşitlik, karşılaştırılan nesne referansları anlamına gelir.   aynı nesne Bitwise eşitlik, karşılaştırılan nesnelerin sahip olduğu anlamına gelir.   Aynı ikili gösterim.

1
katma

Değer türlerini kutladığınızda neler olduğu hakkında daha fazla bilgi edinmek için, Shivprasad bunu burada oldukça kısaca açıklıyor:

Boks ve Unboxing

Değer türlerini nesnelere boks ettiğiniz için artık referans eşitliği yapıyorsunuz demektir. Şu anda örneğinizdeki farklı bellek konumlarında bulundukları için yanlış dönecektir.

1
katma

Çünkü Equals nesne referansının adresini karşılaştırır ve iki sayı farklı konumlarda saklanır. İki değer türünü karşılaştırırsanız, Eşitlik, float, int, string ve diğer türler için geçersiz kılındığından doğru şekilde davranır.

0
katma

Çünkü farklı memeori hücrelere atandılar. 2 nesne = sadece aynı nesne olduğunda. Float ve int kısmında, çalışma zamanı değerini kontrol ettiğinden 2 değişkenini test ettiğinizde doğru olur. bu kadar!

0
katma

Nesne için bir değer türü yayınladığınızda, aslında yığına yerleştirilir ve == bu noktada referansları karşılaştırır, ki bu yanlış olur. (Basitleştirilmiş)

0
katma