惊人的元组(in)平等

时间:2011-02-21 18:24:16

标签: c# equality tuples

直到今天,我对.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>似乎总是被认为是不相等的,无论两个实例都可以包装同一个对象(盒装或类型转换 - 它们都是相同的)。< / p>

这真的是Tuples的行为吗?结构兼容性实际上是对平等的附加约束,而不是放松,因为我一直在解释它直到现在?

如果是这样,BCL中还有其他东西可以用来满足上述单元测试的期望吗?

提前谢谢!

3 个答案:

答案 0 :(得分:45)

对于要被视为“相等”的对象,元组需要满足以下条件:

  • 必须是具有与当前对象相同数量的通用参数的元组对象。
  • 每个通用参数必须与另一个相同。
  • 元组的每个成员必须具有与另一个成员相同的值。

因此,因为Tuple<object>具有与Tuple<string>不同的泛型参数,所以即使该对象实际上是对与强类型{的相同值的字符串的引用,它们也不相等。 {1}}。

答案 1 :(得分:19)

是的,我会说这是元组应该如何表现的。您在这里有两种不同的元组类型 - Tuple<string>Tuple<object>

documentation for Tuple<T1>.Equals表示其中两个条件是:

  
      
  • 这是Tuple<T1>对象。
  •   
  • 其单个组件与当前实例的类型相同。
  •   

如果您询问Tuple<string>是否等于Tuple<object>,则不是这样,所以它返回false。

总的来说,我认为两种不同类型的实例彼此相等是一个非常糟糕的主意。它引发了各种各样的问题。

答案 2 :(得分:3)

  

这真的是元组应该如何表现吗?结构兼容性实际上是对平等的另一个限制,而不是放松,因为我一直在解释它直到现在?

Tuple<T1>实现了IStructuralEquatable - 就其名称而言,它正是如此 - 检查结构和内容。

你总是可以修改你的单元测试来检查元组的Item内容是否相等,而不是元组本身。