2012-11-14 19 views
11

私はいくつかのユニットテストを書いていると、次のアサーションが失敗:なぜAssert.AreEqual()は比較する前にオブジェクトにキャストしますか?

Assert.AreEqual(expected.Episode, actual.Episode); 

私が代わりにこれを呼び出した場合、それは成功します。

Assert.IsTrue(expected.Episode.Equals(actual.Episode)); 

私はAssert.AreEqual()が最終的にのためにEquals()メソッドを呼び出すことを想定していましたこの場合はEpisode.Equals()と入力します。これはAreEqual()方法は、両方のキャストされていることを私に暗示

public static void AreEqual<T>(T expected, T actual, string message, params object[] parameters) 
{ 
    if (object.Equals((object)expected, (object)actual)) 
     return; 
    Assert.HandleFail... 
} 

はしかし、Microsoft.VisualStudio.TestTools.UnitTesting.Assertでカバーの下に私は(ReSharperので逆コンパイル)、次のコードを見つけましたexpectedactual~objectは、Episodeクラスで記述したオーバーロードではなく、ベースの使用を強制的に行うために使用されます(Equals())。基本メソッドは、参照が同じであるかどうかを確認するだけです。

私は2つの質問があります。

  1. は私の説明が実際に正しいですか、私が何かを見逃していますか?
  2. なぜフレームワークはそのメソッドのオーバーロードではなくobject.Equals()の使用を強制しますか?

それは、関連するなら、ここに私の方法は次のとおりです。

public bool Equals(Episode other) 
{ 
    return Number == other.Number && 
      CaseNote.Equals(other.CaseNote) && 
      Patient.Equals(other.Patient); 
} 
+0

Offtopic:どのバージョンのReSharperを逆コンパイルできますか? – sll

+0

私は、そこにどれくらいの時間があったのか分かりませんが、私の経験では少なくともv5です。内部オブジェクトに対して初めてF12(宣言に行く)では、あなたがしたいことを尋ねます。オプションの1つは逆コンパイルです。 Jetbrainsからの無料のスタンドアロンデコンパイラもあります。 –

+1

btw、表示されるメソッドは*オーバーロード*であり、オーバーライドではありません。 –

答えて

6

それはのようなものを扱ってobject.Equals(object,object)、使用している:

  • は、それらは同じ参照されていますか?
  • は、いずれかまたは両方であるnullリファレンス?

、その後は、それらのものを処理した後にx.Equals(y)を使用するために行きます。 objectにキャストする必要があります。その理由は、object.Equals(object,object)のためです。 objectに鋳造することは、ボックスがnullまたは普通のボックスTのいずれかになるので、Nullable<T>でのいくつかの合併を回避します。任意のボクシングなし

Nullable<T>を扱う
if (EqualityComparer<T>.Default.Equals(expected,actual)) 
    return; 

IEquatable<T>classstruct、およびその他のいくつかのシナリオ:

はしかし、それはまた、として実装されている可能性があります。

しかし、現在の実装では仕事が行われ、時折のボックスは世界の終わりではありません(また、あなたのタイプがclassならボクシングは問題でもありません)。

+0

[Nullable 'でオブジェクトにキャストしてnullをチェックすると、パフォーマンス上の影響が避けられます](http://stackoverflow.com/q/12396457/50776)(あなたのせいではありません。 – casperOne

+0

@casperOneだから、もし私が書いていたら*私は 'EqualityComparer 'を使っていましたが**これには苦しんでいません。 –

+0

この回答は正しいものの、OPが真実に見えるとOPが偽りに見える理由を説明することはできません。ここでの主な問題は、彼は 'Equals(Episode other) 'のみを実装し、' Equals(other object)'では実装していないことです。 – Servy

4

コードでは、Equals(object other)もオーバーライドする必要があります(また、GetHashCodeもオーバーライドする必要があります)。

はちょうど2つのオブジェクトが等しい場合GetHashCodeメソッドのために、彼らはも同じハッシュコードを返す必要があります覚えて、あなたのコード

public bool Equals(Episode other) 
{ 
    return Number == other.Number && 
      CaseNote.Equals(other.CaseNote) && 
      Patient.Equals(other.Patient); 
} 

public override bool Equals(object other) 
{ 
    Episode castOther = other as Episode; 
    if(castOther == null) 
     return false; 
    return this.Equals(castOther); 
} 

public override int GetHashCode() 
{ 
    //TODO: Implement using the members you used in "Equals(Episode other)" 
    throw new NotImplmentedExecption(); 
} 

にこれを追加します。ここでは、視覚化を支援するための簡単な図があります。

enter image description here

あなたは同様の問題のためにCaseNotePatientをチェックすることもできます。

+0

あなたの役に立つ答えをありがとう。私はこれが実際には*私のコードが2つのアサーションに対して異なる結果を返す理由であることを認識しています。 –

関連する問題