2017-04-18 44 views
-2

我保持一個代碼庫,我已經發現了兩個擴展方法,處理檢查對象的結構平等,這是我不喜歡所有的(一個調用另一個):通用平等檢查

public static bool IsObjectEqual<T>(this T obj, T obj2) 
{ 
    foreach (var pi in obj.GetType().GetProperties()) 
    { 
     var enumerable1 = pi.GetValue(obj, null) as IEnumerable; 
     var enumerable2 = pi.GetValue(obj2, null) as IEnumerable; 

     if (enumerable1 != null) 
     { 
      foreach (var item in enumerable1) 
      { 
       if (enumerable2 == null || !((object[])enumerable2).Contains(item)) 
       { 
        return false; 
       } 

      } 
     } 
     else if (!IsPropertyInfoValueEqual(pi, obj, obj2)) 
     { 
      return false; 
     } 
    } 

    return true; 
} 

private static bool IsPropertyInfoValueEqual<T>(PropertyInfo pi, T obj, T obj2) 
{ 
    var val = pi.GetValue(obj, null); 
    var val2 = pi.GetValue(obj2, null); 

    if (val != null && val2 != null) 
    { 
     return val.Equals(val2); 
    } 

    return (val == null && val2 == null); 
} 

問題是,我有想出一個場景的麻煩,我想他們會失敗,或者會出現問題。我在我的水域知道他們錯了,我不能把它放在手指上。

在實現相等性檢查時,我總是使用IEquateable<T>,所以沒有任何處理平等的框架類/接口是調用我的spidey感覺的一件事情。我意識到這種方法試圖成爲一種廣義的,基於反思的方法,但它讓我感到緊張(如前所述)。

任何人都可以看到這些方法是合法的問題?

編輯

大合法問題的方法。轉換爲object []會導致InvalidCastException。

+0

這感覺有點像一個代碼審查的問題。 –

+0

它是,但沒有人去那個網站。 – onefootswill

+0

這並不意味着它應該在這裏發佈。 –

回答

1

有可能是別人的,但我看到了兩個主要問題與此代碼:

  1. 反思是昂貴的。真的很貴。要在如此大的範圍內使用它就像平等檢查一樣簡單,這只是一個壞主意。該代碼甚至不會緩存對象圖,所以它每次都必須執行的全反射。在相當常見的情況下,我可以看到這種方法是性能瓶頸。

  2. 如果成員是IEnumerable,代碼將無法正常工作。其他一切都與反思進行比較,但收集比較使用Contains。這將做簡單的引用相等(至少對於引用類型)並且不重用反射方法。這可能會導致這種方法的用戶產生不希望的結果。

實施IEquatable和朋友是一個更快,更安全的方法。實現者可以明確地決定比較如何工作,而且你不需要任何反思。