C# 通用平等检查器

C# 通用平等检查器,c#,equality,C#,Equality,我正在维护一个代码库,我发现了两个扩展方法,用于检查对象的结构相等性,我一点也不喜欢(一个调用另一个): public static bool IsObjectEqual(此T obj,T obj2) { foreach(obj.GetType().GetProperties()中的var pi) { var enumerable1=pi.GetValue(obj,null)作为IEnumerable; var enumerable2=pi.GetValue(obj2,null)作为IEnume

我正在维护一个代码库,我发现了两个扩展方法,用于检查对象的结构相等性,我一点也不喜欢(一个调用另一个):

public static bool IsObjectEqual(此T obj,T obj2)
{
foreach(obj.GetType().GetProperties()中的var pi)
{
var enumerable1=pi.GetValue(obj,null)作为IEnumerable;
var enumerable2=pi.GetValue(obj2,null)作为IEnumerable;
如果(enumerable1!=null)
{
foreach(enumerable1中的变量项)
{
如果(enumerable2==null | |!((对象[])enumerable2).Contains(项))
{
返回false;
}
}
}
如果(!IsPropertyInfoValueEqual(pi、obj、obj2))为else,则为
{
返回false;
}
}
返回true;
}
私有静态布尔值IsPropertyInfoValueEqual(PropertyInfo pi、T obj、T obj2)
{
var val=pi.GetValue(obj,null);
var val2=pi.GetValue(obj2,null);
if(val!=null&&val2!=null)
{
返回val.Equals(val2);
}
返回值(val==null&&val2==null);
}
问题是,我很难想出一个我认为他们会失败或导致问题的方案。我深知他们错了,我就是不能指指点点

在实现平等性检查时,我总是使用
iequatable
,因此没有任何处理平等性的框架类/接口是我的spidey感觉的一个原因。我意识到这种方法试图成为一种普遍的、基于反思的方法,但它让我感到紧张(如上所述)

有人能看出这些方法存在合法问题吗

编辑


这些方法存在很大的合法性问题。对对象[]的强制转换会导致InvalidCastException。

可能还有其他异常,但我发现此代码存在两个主要问题:

  • 反射是昂贵的。真的很贵。在如此大规模的情况下,将它用于等式检查这样简单的事情,这是一个坏主意。代码甚至不缓存对象图,因此每次都必须进行完全反射。在相当常见的情况下,我可以看到这种方法是一个性能瓶颈

  • 如果成员是
    IEnumerable
    ,则代码将无法按预期工作。其他所有内容都与反射进行比较,但是使用
    Contains
    对集合进行比较。这将实现简单的引用相等(至少对于引用类型),并且不会重用反射方法。这可能会导致此方法的用户产生不希望的结果


  • 实施
    IEquatable
    和friends是一种更快、更安全的方法。实现者可以明确地决定比较是如何工作的,您不需要任何反思。

    这感觉像是一个代码审查问题。是的,但根本没有人访问该网站。这并不意味着它应该发布在这里。@BradleyDotNET非常感谢Bradley。请随意发表您的评论作为回答。我不担心落选。只要人们帮助我。
    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);
    }