2009-04-25 14 views
5

自分自身を検証しようとしている間に、IEnumerablesのC#Equalsが参照と等しいことがわかりました。 NUnitのC#Assert.AreNotEqual対Equals

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を使っていたという概念に縛られていたと思います。

答えて

9

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

Assert.AreNotEqualはこれより少し賢いです。これはEqualsメソッドと異なり、デバッグの目的で設計されているため、IEnumerable<T>を特別な型として認識するため、実際には2つの列挙によって生成されたシーケンスを比較します。 2つのパラメータが数値的には同じだが値の異なるタイプ(たとえばshortおよびlong)の場合は、trueを返すなど、他の面白いことに気付くはずです。

希望に役立ちます。

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