我有以下实体
public class Employee
{
public int EmpId { get; set; }
}
如何比较对象? 感谢
答案 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;
}