比较两个对象

时间:2011-07-28 06:50:06

标签: c#

我有以下实体

public class Employee
{
    public int EmpId { get; set; }
 }

如何比较对象? 感谢

4 个答案:

答案 0 :(得分:5)

在您的类型上实施IEquatable<T>(在本例中为Employee),然后使用Enumerable.SequenceEqual

bool equal = Enumerable.SequenceEqual(lst1, lst2);

如果您无法修改Employee课程,则还可以为Employee创建自定义IEqualityComparer<T>,并使用Enumerable.SequenceEqual的其他重叠。

bool equal = lst1.SequenceEqual(lst2, new EmployeeComparer());

请注意,只有当两个集合包含相同顺序的相同对象时才会认为它们相等。

如果物品的顺序无关紧要,我会使用类似的东西:

bool equal = lst1.Count == lst2.Count && lst1.Count == lst1.Intersect(lst2).Count();

您还可以将IEqualityComparer<T>Intersect一起使用。

<强>更新

似乎您希望能够比较任何对象,即使它们没有实现IEquatable<T>。下面是一个相等比较器的示例,如果它是可用的,将使用IEquatable<T>,如果类型是一个集合,则使用Enumerable.SequenceEqual,否则使用反射以递归方式检查该类型的公共属性:

class ReflectionComparer<T> : IEqualityComparer<T>
{
    public bool Equals(T x, T y)
    {
        Type type = typeof(T);
        if( typeof(IEquatable<T>).IsAssignableFrom(type) )
            return EqualityComparer<T>.Default.Equals(x, y);

        Type enumerableType = type.GetInterface(typeof(IEnumerable<>).FullName);
        if( enumerableType != null )
        {
            Type elementType = enumerableType.GetGenericArguments()[0];
            Type elementComparerType = typeof(ReflectionComparer<>).MakeGenericType(elementType);
            object elementComparer = Activator.CreateInstance(elementComparerType);
            return (bool)typeof(Enumerable).GetMethod("SequenceEqual")
                                           .MakeGenericMethod(elementType)
                                           .Invoke(null, new object[] { x, y, elementComparer });
        }

        foreach( PropertyInfo prop in type.GetProperties() )
        {
            Type propComparerType = typeof(ReflectionComparer<>).MakeGenericType(prop.PropertyType);
            object propComparer = Activator.CreateInstance(propComparerType);
            if( !((bool)typeof(IEqualityComparer<>).MakeGenericType(prop.PropertyType)
                                                   .GetMethod("Equals")
                                                   .Invoke(propComparer, new object[] { prop.GetValue(x, null), prop.GetValue(y, null) })) )
                return false;
        }
        return true;
    }

    public int GetHashCode(T obj)
    {
        throw new NotSupportedException();
    }
}

我没有实施GetHashCode,因为Enumerable.SequenceEqual不需要它。

这应该可以做你想要的(但要注意这不是很有效;不要在性能关键代码中使用它。)

答案 1 :(得分:1)

您需要为对象实现IEqualityComparer,然后在Union方法

中使用它

答案 2 :(得分:0)

覆盖Employee类

中的Equals()和GetHashCode()方法
public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }
    public int EmpAge { get; set; }
    public string EmpSex { get; set; }

    public override bool Equals(object obj)
    {
        Employee other = obj as Employee;
        return null != other
               && other.EmpId == this.EmpId
               && other.EmpName == this.EmpName
               && other.EmpAge == this.EmpAge
               && other.EmpSex == this.EmpSex;
    }

    public override int GetHashCode()
    {
        return (EmpId + "_" + EmpName + "_" + EmpAge + "_" + EmpSex).GetHashCode();
    }
}


bool AreEqual<T>(IEnumerable<T> ls1, IEnumerable<T> ls2)
{
    return ls1.Count() == ls2.Count() && !ls1.Any(e => !ls2.Contains(e)) && !ls2.Any(e => !ls1.Contains(e));
}

    void Test()
    {
        Employee e1 = new Employee() { EmpAge = 20, EmpId = 123, EmpName = "XYZ", EmpSex = "M" };
        Employee e2 = new Employee() { EmpAge = 20, EmpId = 1232, EmpName = "XYZ", EmpSex = "M" };
        Employee e3 = new Employee() { EmpAge = 20, EmpId = 1232, EmpName = "XYA", EmpSex = "M" };
        Employee e4 = new Employee() { EmpAge = 20, EmpId = 1232, EmpName = "XYF", EmpSex = "M" };

        List<Employee> ls1 = new List<Employee>{e4, e3, e1, e2};
        List<Employee> ls2 = new List<Employee>{e1, e2, e3, e4};

        bool result = AreEqual(ls1, ls2); // true

        ls1 = new List<Employee>{e4, e3, e1, e3};
        ls2 = new List<Employee>{e1, e2, e3, e4};

        result = AreEqual(ls1, ls2); // false
    }

答案 3 :(得分:0)

如果你打算比较任何类型的两个实例,你可能会想到在这里使用反射但是我确信这不是正确的方法,我们只是利用框架。

作为黑客攻击解决方案,您可能会看到以下代码。

 static void Main(string[] args)
    {
        Employee e1 = new Employee() { EmpAge = 20, EmpId = 123, EmpName = "XYZ", EmpSex = "M" };
        Employee e2 = new Employee() { EmpAge = 20, EmpId = 123 , EmpName = "XYq", EmpSex = "M" };

        Person p1 = new Person() { Age = 20, name ="ABC"  };
        Person p2 = new Person() { Age = 20, name = "ABC" };

        Console.WriteLine("Employee Equality :" + IsObjectEquals(e1, e2).ToString());
        Console.WriteLine("Person Equality :" +IsObjectEquals(p1, p2).ToString());
        Console.ReadLine();
    }


    public static bool IsObjectEquals(object obj1, object obj2)
    {

       PropertyInfo[] props1 = obj1.GetType().GetProperties();
       PropertyInfo[] props2 = obj2.GetType().GetProperties();



       foreach (PropertyInfo pinfo in props1)
       {
           var val1 = pinfo.GetValue(obj1, null);
           var val2 = pinfo.GetValue(obj2, null);

           if (val1.ToString().Trim() != val2.ToString().Trim())
           {
                    return false;
           }


       }

       return true;

    }