2017-04-18 45 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和朋友是一个更快,更安全的方法。实现者可以明确地决定比较如何工作,而且你不需要任何反思。