我有以下实体
public class Employee
{
public int EmpId { get; set; }
}
我该如何比较两个对象?谢谢。
我有以下实体
public class Employee
{
public int EmpId { get; set; }
}
我该如何比较两个对象?谢谢。
在您的类型(在此示例中为Employee
)上实现IEquatable<T>
,然后使用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();
Intersect
和 IEqualityComparer<T>
一起使用。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
不需要它。
这应该能够做到你想要的(但要注意,这并不是非常高效的;不要在性能关键代码中使用它)。
IEqualityComparer<T>
实现,如果没有更好的方法存在,它将使用反射来比较对象。希望这能帮到你。 - Sven您需要为您的对象实现IEqualityComparer
,然后在Union方法中使用它。
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
}
如果您想比较任何类型的两个实例,您可能会考虑使用反射,但我确定这不是正确的方法,我们只是利用了框架。
作为一种破解的解决方案,您可以查看下面的代码。
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;
}