Удивительный кортеж (в) равенстве - PullRequest
25 голосов
/ 21 февраля 2011

До сегодняшнего дня мое понимание классов .NET Tuple заключалось в том, что они делегируют свою реализацию Equals() своему содержимому, что позволяет мне приравнивать и сравнивать их "по значению".

Тогда этоТест пришел и сделал из меня дурака:

[TestMethod]
public void EquateTwoTuplesWithSameContent()
{
    var t1 = Tuple.Create("S");
    var t2 = Tuple.Create((object)t1.Item1);
    Assert.IsTrue(t1.Equals(t2)); // Boom!
}

Чтение документации MSDN и различных блогов оставило мне больше вопросов.Из того, что я понял, может показаться, что Tuple<object> и Tuple<TWhatever> всегда считаются не равными, независимо от того, что оба экземпляра могут обернуть один и тот же объект (в штучной упаковке или в typecast - это все одинаково).* Это действительно, как Tuples должен вести себя?Является ли структурная совместимость на самом деле дополнительным ограничением на равенство, а не ослаблением, как я его интерпретировал до сих пор?

Если так, есть ли в BCL что-нибудь еще, что я могуиспользовать, чтобы оправдать ожидания вышеупомянутого модульного теста?

Заранее спасибо!

Ответы [ 3 ]

45 голосов
/ 21 февраля 2011

Кортежи требуют, чтобы для объектов, которые считаются "равными", выполнялось следующее:

  • Должен быть объектом Tuple с тем же числом общих параметров, что и у текущего объекта.
  • Каждый из этих общих параметров должен быть того же типа, что и другие.
  • Каждый член кортежа должен иметь то же значение, что и соответствующий член другого.

Таким образом, поскольку Tuple<object> имеет общий параметр, отличный от Tuple<string>, они не равны, даже если объект на самом деле является ссылкой на строку того же значения, что и строго типизированный Tuple<string>.

19 голосов
/ 21 февраля 2011

Да, я бы сказал, что так должны себя вести кортежи.Здесь у вас есть два разных типа кортежей - Tuple<string> и Tuple<object>.

В документации для Tuple<T1>.Equals указано, что два условия:

  • Это Tuple<T1> объект.
  • Его единственный компонент того же типа, что и текущий экземпляр.

Это неверно, если выспросите, равен ли Tuple<string> значению Tuple<object>, чтобы он возвращал ложное значение.

В общем, я думаю, что это очень плохая идея, когда экземпляры двух разных типов считаются равными друг другу.Он предлагает все виды вопросов.

3 голосов
/ 21 февраля 2011

Это действительно, как должны вести себя кортежи? Является ли структурная совместимость на самом деле дополнительным ограничением равенства, а не ослаблением, как я его интерпретировал до сих пор?

Tuple<T1> реализует IStructuralEquatable - который, по своему названию, делает именно это - проверяет структуру и содержимое.

Вы всегда можете переделать свой юнит-тест, чтобы проверить на предмет равные элементы содержимого кортежа, а не сам кортеж.

...