【问题标题】:Surprising Tuple (in)equality令人惊讶的元组(不)等式
【发布时间】:2011-02-21 18:24:15
【问题描述】:

直到今天,我对 .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> 似乎总是被认为是不相等的,不管这两个实例可能包装同一个对象(装箱或类型转换 - 都是一样的)。

这真的是Tuples 应该表现的方式吗?结构兼容性实际上是对平等的附加约束,而不是放松,正如我一直在解释它吗?

如果是这样,我可以使用 BCL 中的其他内容来满足上述单元测试的期望吗?

提前谢谢你!

【问题讨论】:

    标签: c# equality tuples


    【解决方案1】:

    元组需要满足以下条件才能使对象被视为“相等”:

    • 必须是具有与当前对象相同数量的泛型参数的 Tuple 对象。
    • 这些泛型参数中的每一个都必须与另一个的类型相同。
    • 元组的每个成员的值必须与另一个对应成员的值相同。

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

    【讨论】:

    • 那么,一般来说,一种思考方式是“类型参数中没有协方差”?或者这种现象是Tuple 类型独有的?
    • 啊。 This SO question 回答我的问题。 “...只有接口和委托类型支持泛型变化...”
    • @radarbob:虽然它提出了一个问题,但为什么没有ITuple<out T> 接口?
    • @TDaver:因为元组实现了 IStructuralEquatable,因此它们允许您定义自己的方法来确定相等性。您可以实现一个 TupleEqualityComparer 来削弱默认比较的第二条规则,以便泛型类型不必相同,但分配的类型必须相同。 .NET 团队的工作量要少得多(尽管您需要做更多的工作)。
    • 请注意,这仅适用于Equals。元组不会覆盖==,因此会进行参考检查。令人讨厌的令人惊讶的行为 IMO。
    【解决方案2】:

    是的,我想说这就是元组的行为方式。这里有两种不同的元组类型 - Tuple<string>Tuple<object>

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

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

    如果你问Tuple<string> 是否等于Tuple<object>,那不是真的,所以它返回 false。

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

    【讨论】:

    • 其实,我认为这是文档中指定的第二条规则;单个组件属于同一类型。它们都是Tuple<T1>s,每个只有一个泛型参数,但参数不同,因此组件类型不匹配。
    • @KeithS:据说这不是Tuple<T1>,它是一些X 的Tuple<X>,但我同意你的观点。我也会添加第二个要点:)
    【解决方案3】:

    这真的是元组应该表现的方式吗?结构兼容性实际上是对平等的额外约束,而不是放松,正如我一直在解释的那样?

    Tuple<T1> 实现 IStructuralEquatable - 顾名思义,它就是这样做的 - 检查结构和内容。

    您总是可以重新编写单元测试来检查元组的 Item 内容是否相等,而不是检查元组本身。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      相关资源
      最近更新 更多