чому однакові не працюють однаково, коли об'єкти відкидаються на об'єкт?

коли я закидаю інтроміту і плаваю, щоб об'єкнутися і порівнювати їх, рівність завжди помилкова. Чому?

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

Оновлення: це НЕ випадок для одного і того ж типу

        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 Відповіді

float дорівнює лише іншому float , а int дорівнює лише іншому int . Єдиними рядками, які повертають true , є такі:

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

В обох випадках існує неявне перетворення значення i в float , тому вони еквівалентні:

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

Ці переходи - це лише звичайні перетворення, необхідні для вирішення проблеми перевантаження методів та операторів.

Жоден з решти рядків не пов'язаний із неявним перетворенням, тому вони порівнюють два різних типи, що дає результат false , навіть якщо він порівнює значення ( що стосується всіх викликів Equals ). Ось чому, використовуючи Equals , значення коду int робить повернення true , оскільки це порівнює два значення одного і того ж типу , за значенням .

В цьому випадку:

Console.WriteLine(obi == obf);

він навіть не намагається порівнювати числові значення - це порівнює посилання для об'єктів у коробці. Оскільки є два різні посилання, результат - false - і буде навіть якщо обидва значення мають тип int .

10
додано
@Чарлс Ламберт: так. Подивіться на IL, і ви побачите, що воно виконується.
додано Автор Jon Skeet, джерело
чи неявне перетворення обробляється під час компіляції?
додано Автор Charles Lambert, джерело

Інші вже пояснили, чому == не працює, як очікується, у ваших об'єктах.

Що стосується вашого редагування: oi1.Equals (oi2) працює, оскільки Equals - це віртуальна функція, і, таким чином, .

true , якщо obj - це екземпляр Int32 і дорівнює значенню цього екземпляра; інакше невірно .

Це також пояснює, чому obi.Equals (obf)) повертає false: obf не є прикладом Int32.

3
додано

Ви боксуєте int та плаваєте до об'єкта, а це означає, що вони порівнюються як посилання. Оскільки вони не є посиланнями на один і той же об'єкт, вони не рівні.

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

1
додано

Коли ви оголосили два об'єкти, вони посилаються на іншу пам'ять:

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

але спробуйте наступне, дозвольте одному об'єкту посилання на інший:

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

MSDN, Object.Equals Method

За замовчуванням реалізація Equals підтримує еталонну рівність для   типи референтів та побітну рівність для типів значень. Посилання   рівність означає, що об'єктні посилання, які порівнюються, відносяться до   той же об'єкт Побіжна рівність означає об'єкти, що порівнюються   однакове подвійне подання.

1
додано

Щоб довідатися більше про те, що трапляється, коли ви кодуєте значення, Shivprasad описує це досить коротко тут:

Бокс та розблокування

Оскільки ви боксуєте типи значень для об'єктів, тепер ви виконуєте рівноправність посилання. Оскільки вони зараз перебувають у різних місцях пам'яті у вашому прикладі, вони повернуться помилково.

1
додано

Оскільки Equals порівнює адресу посилання об'єкта, а два номери зберігаються в різних місцях. якщо порівнювати два типи значень, Equals поводиться коректно, оскільки воно було скасовано для поплавкових, int, stringних та інших типів.

0
додано

Оскільки вони призначені для різних метиорних клітин. 2 об'єкти = якщо вони є одним і тим же об'єктом. У поплавці та int частини ви отримаєте вірне значення, коли ви перевіряєте 2 змінні, оскільки runtime перевіряє їх значення. це все!

0
додано

Коли ви кладете тип значення до об'єкта, він фактично стає вкладено в купу, і == порівнює посилання в цій точці, яка буде невірною. (Спрощена)

0
додано
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug