問題: 寫單元測試時,需要對比兩個對象是否相等,如果使用
Assert.AreEqual(mockclass1, class1)
永遠無法通過。
原因: 這裡使用了
object
預設的
Equals
方法,必須要引用同一個對象,才會傳回
true
。預設的
Equals
方法實作的隻是同一性(identity),而不是相等性(equality)。
合理的
Equals
方法本應該這樣實作:
- 如果
實參為空,就傳回obj
,因為調用的是非靜态false
方法,Equals
辨別的目前對象肯定不為空;this
- 如果
和this
實參引用同一個對象,就傳回obj
。在比較大量字段時,這一步有助于提升性能;true
- 如果
和this
實參引用不同類型的對象,就傳回obj
;false
- 針對類型定義的每個執行個體字段,将
對象中的值與this
對象中的值進行比較,任何字段不相等,傳回obj
;false
- 調用基類的
方法比較它定義的任何字段,傳回基類的Equals
結果。Equals
由于
Microsoft
并沒有這樣實作
Equals
,是以需要針對不同的對象重寫
Equals
方法,為了仍然能測試同一性,
Object
提供了靜态方法
ReferenceEquals
。
同一性
檢查同一性(看兩個引用是否指向同一個對象),務必調用
ReferenceEquals
,不應該使用
==
操作符,因為類型可能重載了操作符。
相等性
重寫
Equals
方法時,除了上文所講的,還應該做下面幾件事:
- 讓類型實作
接口的System.IEquatable<T>
Equals
方法。
這個泛型接口允許定義類型安全的
方法,在重寫的Equals
方法中調用這個類型安全的方法。Equals(object obj)
- 重載
和==
操作符方法。!=
- 如果需要排序而比較類型的執行個體,還應該實作
的System.IComparable
方法以及各種比較操作符。CompareTo
- 重寫類型的
GetHashCode
方法。
由于在
、System.Collections.Hashtable
以及其他一些集合的實作中,要求兩個對象必須具有相同的哈希碼才被視為相等。System.Collections.Generic.Dictionary
具體例子如下,完整可參考 MSDN IEquatable.Equals(T) Method:
public class Person : IEquatable<Person>
{
private string _name;
private string _id;
public Person(string name, string id)
{
_name = name;
_id = id;
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Id
{
get{ return _id; }
set{ _id = value; }
}
//自定義的Equals方法
public bool Equals(Person other)
{
if (other == null) return false;
if (_name == other.Name && _id == other.Id)
return true;
else
return false;
}
//重寫基類中的Equals方法
public override bool Equals(object obj)
{
if (obj == null) return false;
Person personObj = obj as Person;
if (personObj == null)
return false;
else
return Equals(personObj);
}
public override int GetHashCode()
{
return _name.GetHashCode() ^ _id.GetHashCode();
}
}
拓展閱讀:
https://www.cnblogs.com/yang_sy/archive/2014/03/07/3582946.html