惊人的元组(in)平等

aov*_*ven 27 c# tuples equality

直到今天,我对.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!
}
Run Code Online (Sandbox Code Playgroud)

阅读MSDN文档和各种博客给我留下了更多问题.从我收集的内容来看,似乎Tuple<object>并且Tuple<TWhatever>总是被认为是不相等的,无论两个实例都可以包装相同的对象(盒装或类型转换 - 它们都是相同的).

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

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

先感谢您!

Kei*_*thS 47

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

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

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

  • 啊.[这个问题](http://stackoverflow.com/questions/2872867/is-c-sharp-4-0-tuple-covariant)回答了我的问题."......只有接口和委托类型支持通用差异..." (2认同)
  • @TDaver:因为Tuples实现了IStructuralEquatable,所以它们允许您定义自己的方法来确定相等性.您可以实现一个TupleEqualityComparer,它会削弱默认比较中的第二个规则,因此泛型类型不必相同,但分配的类型可以..NET团队的工作少得多(尽管为您工作更多). (2认同)
  • 请注意,这仅适用于“等于”。元组不会覆盖`==`,因此会进行引用检查。在我看来,令人讨厌的令人惊讶的行为。 (2认同)

Jon*_*eet 19

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

有两个条件的州的文件Tuple<T1>.Equals:

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

如果你问a Tuple<string>是否等于a Tuple<object>,那就不是这样,所以它返回false.

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