Подтвердить что ты не робот

Удивительное равенство Tuple (in)

До сегодняшнего дня мое понимание классов .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, которое я могу использовать для удовлетворения ожиданий вышеупомянутого unit test?

Заранее благодарю вас!

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Это неверно, если вы спросите, равен ли Tuple<string> Tuple<object>, поэтому он возвращает false.

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

Ответ 3

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

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

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