5

在尝试向自己验证时,IEnumerables 的 C# Equals 是一个引用 equals,我发现了一些奇怪的东西。在 NUnit 中进行以下设置

var a = (IEnumerable<string>)(new[] { "one", "two" });
var b = (IEnumerable<string>)(new[] { "one", "two" });

这个测试

Assert.IsFalse(a.Equals(b));

通过,而这个测试

Assert.AreNotEqual(a, b);

没有。谁能解释为什么?

编辑:感谢您的回答。我刚刚阅读了 NUnit 的文档,它说了同样的话,即带有集合的 AreEqual 和 AreNotEqual 测试集合中每个元素的相等性。我想我被这个概念困住了,AreEqual 和 AreNotEqual 只是使用普通的 Equals。

4

2 回答 2

9

调用a.Equals(b)返回false是因为 a 和 b 不是相同的对象(尽管它们当然是相同的枚举)。除非被覆盖,否则该Equals方法会自动通过引用比较对象,这就是在这种情况下发生的情况。

Assert.AreNotEqual比这更聪明一点。与方法不同,它是为调试目的而设计的Equals,因此它实际上比较了两个枚举产生的序列,因为它被识别IEnumerable<T>为一种特殊类型。您还应该注意到它还做了其他有趣的事情,例如true当两个参数在数值上相同但值类型不同(例如shortlong)时返回。

希望有帮助。

于 2009-04-25T22:24:42.770 回答
1

我没有查看 NUnit 源代码来了解 NUnit 人如何编码 AreNotEqual。但是,我可以告诉你它是如何为具有相同行为的 MbUnit 完成的。

首先在 AssertNotEqual(a, b) 中通过执行如下代码检查引用是否相等:

    if (Object.ReferenceEquals(left, right))
        return true;

在你的情况下,它会失败。接下来它检查对象是否为 IEnumerable 类型。如果是,则遍历它们并比较这些项目是否相同且顺序相同。

但是,IEnumerable 中的 T 类型比 MbUnit 中的字符串或 ValueType 更复杂 AssertNotEqaual(a, b) 不会失败。

    var a = (IEnumerable<StringBuilder>)(new[] { new StringBuilder("one"), new StringBuilder("two") });
    var b = (IEnumerable<StringBuilder>)(new[] { new StringBuilder("one"), new StringBuilder("two") });

    Assert.IsFalse(a.Equals(b));  // Success
    Assert.AreNotEqual(a, b);     // Success
于 2009-04-25T22:59:27.243 回答