直到今天,我对.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中还有其他东西可以用来满足上述单元测试的期望吗?
提前谢谢!
答案 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内容是否相等,而不是元组本身。