Кортеж == Путаница - PullRequest
       17

Кортеж == Путаница

16 голосов
/ 22 марта 2012

Предположим, я определил два кортежа:

Tuple<float, float, float, float> tuple1 = new Tuple<float, float, float, float>(1.0f, 2.0f, 3.0f, 4.0f);
Tuple<float, float, float, float> tuple2 = new Tuple<float, float, float, float>(1.0f, 2.0f, 3.0f, 4.0f);

Если я пытаюсь сравнить кортежи, я получаю разные результаты

bool result1 = (tuple1 == tuple2);    // FALSE
bool result2 = tuple1.Equals(tuple2); // TRUE

Я ожидаю, что оба вызова вернут истину. Что именно == сравнивает?

Ответы [ 3 ]

32 голосов
/ 22 марта 2012

Для Tuple == сравнивает ссылки на объекты, потому что он не перегружает оператор ==.Поскольку объекты эквивалентны, но не являются одним и тем же конкретным экземпляром, Equals() возвращает true, а == возвращает false.

Многие типы не перегружают ==, некоторые предпочитают сохранять различиемежду Equals() для эквивалентности и == для ссылочного равенства.

Кроме того, использование == для эквивалентности может привести к некоторой странности:

public bool AreSame<T>(T first, T second) where T : class
{
    return first == second;
}

Приведенный выше код всегда проверяет равенство ссылок, поскольку неограниченный родовой объект считается objectво время компиляции, таким образом, если метод не является виртуальным, вы получите версию объекта (даже если тип, такой как string перегружает ==).

Таким образом, это использование приведенного выше кода:

var x = "Hello";
var y = "H";

// doing concat to avoid string interring
AreSame(x, y+"ello");

Да, строки эквивалентны, да T равно string, но == привязано к == объекта, так как универсальный тип не ограничен, таким образом, это вернет false дажехотя тот же код с явными string параметрами вернет true.

10 голосов
/ 22 марта 2012

== сравнивает ссылки на объекты. Класс Tuple не перегружает оператор ==, поэтому вам нужно использовать .Equals.

9 голосов
/ 22 марта 2012

== для Tuple будут видеть только ссылки, и, следовательно, вы увидите, что это неверно.

PS: Рекомендуется сделать что-то вроде:

var tuple1 = Tuple.Create(1.0f, 2.0f, 3.0f, 4.0f)
...