2012-07-10 85 views
7

由於我的(單元)測試覆蓋率仍然很低,不幸的是,我不得不用很難的方法找到很多錯誤。因此,在重構期間,我主要依賴於C#編譯器的類型檢查。類型安全等於()

今天,我修復了在重構期間由於缺少一行x.Equals(aThingWrappingOriginalThing)而引入的錯誤。因爲它是bool Equals(object T),編譯器沒有抱怨。但是,90%的時間我直接使用Equals()(而不是通過BCL),我打算在邏輯上比較相同類型的對象。

現在我想知道爲什麼我從來沒有見過某人爲這種情況(在C#中)推銷Equals()的類型安全版本。對此有最佳做法嗎?

我很想使用擴展方法對於那些comparisions,就像這樣:

public static bool SafeEquals<T>(this T a, T b) 
{ 
    if (a == null) return b == null; 
    return a.Equals(b); 
} 
public static bool SafeEquals<X>(this IEquatable<X> a, IEquatable<X> b) 
{ 
    if (a == null) return b == null; 
    return a.Equals(b); 
} 

可以將這些進行優化?

這裏是唯一的博客文章,我發現,Java的話題: http://rickyclarkson.blogspot.com/2006/12/making-equalsobject-type-safe.html

+0

以下是有關該主題的一些背景:http://blogs.msdn.com/b/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx – Vlad 2012-07-10 20:16:41

回答

5

您正在尋找

EqualityComparer<T>.Default.Equals(x,y); 

這種支持IEquatable<T>(如果實現的話),其他人使用的潛在拳Equals(object);它支持類和結構,兩者都具有預期的空行爲,包括支持Nullable<T>(沒有裝箱)。

+0

謝謝,聽起來不錯。將它包裝成擴展方法會傷害性能嗎?它會被內聯嗎? – Equalizer 2012-07-11 16:27:40

+0

@Equalizer擴展方法是靜態調用,所以:不是真的,不是。它不太可能被傾斜,因爲.default是一些具體實現中的任何一個實例,具體取決於要使用的策略。該決策/反思每T只進行一次,所以它被緩存 - 但不是內聯。 – 2012-07-11 19:11:21

2

我看到的對我來說很好。

我的2美分:我認爲這將是簡單跳過null檢查,並使用此:

public static bool SafeEquals<T>(this T a, T b) 
{ 
    return object.Equals(a, b); 
} 

有極少數的情況,即會從預期的行爲偏離。其中之一是Equals當兩個對象都是同一個對象時(它永遠不會發生)返回false。

作爲參考,這裏是反編譯object.Equals,所以你可以看到自己會發生什麼。

public static bool Equals(object objA, object objB) 
{ 
    return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB))); 
} 
+0

'對象。 Equals'檢查它們是否指向堆上的相同數據,而不是它們是否相同。 – 2012-07-10 20:24:39

+0

@Kendall這裏的第一個實現只是object.Equals的一個包裝,爲什麼不只是讓消費者調用object.Equals所有它的價值 – Jason 2012-07-10 20:26:01

+0

@ColeJohnson也許默認情況下。但是'Equals'和'ReferenceEquals'之間有區別 – 2012-07-10 20:26:32