5

C# Equals for IEnumerables が参照 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 と b は同じオブジェクトではないため、への呼び出しはa.Equals(b)返されます (もちろん、これらは同じ列挙型ですが)。falseこのEqualsメソッドは、オーバーライドされない限り、参照によってオブジェクトを自動的に比較します。これが、この場合に起こっていることです。

Assert.AreNotEqualこれよりも少し賢いです。メソッドとは異なり、デバッグ目的で設計されているためEquals、実際には、2 つの列挙型によって生成されたシーケンスを比較します。これIEnumerable<T>は、特殊な型として認識されるためです。trueまた、2 つのパラメーターが数値的に同一であるが値の型が異なる場合 (shortと など)に戻るなど、他の興味深いことも行うことに注意してくださいlong

それが役立つことを願っています。

于 2009-04-25T22:24:42.770 に答える
1

私は NUnit のソース コードを見て、NUnit 関係者が AreNotEqual をどのようにコーディングしたかを確認しませんでした。ただし、同じ動作をする MbUnit に対してどのように行われるかを説明できます。

最初に AssertNotEqual(a, b) で、次のようなコードを実行して参照が等しいかどうかを確認します。

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

あなたの場合、それは失敗するでしょう。次に、オブジェクトが IEnumerable 型かどうかをチェックします。そうである場合は、それらを反復して、アイテムが同じで同じ順序であるかどうかを比較します。

ただし、T では IEnumerable の型が string よりも複雑であるか、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 に答える