Compre two objects
I have the below entity
public class Employe开发者_运维技巧e
{
public int EmpId { get; set; }
}
How can I compare between the objects? Thanks
Implement IEquatable<T>
on your type (in this case Employee
), and then use Enumerable.SequenceEqual
:
bool equal = Enumerable.SequenceEqual(lst1, lst2);
If you cannot modify the Employee
class, you can also create a custom IEqualityComparer<T>
for Employee
and use the other overload of Enumerable.SequenceEqual
.
bool equal = lst1.SequenceEqual(lst2, new EmployeeComparer());
Note that this considers two collections equal only if they contain equal objects in the same order.
If the order of the items doesn't matter I would use something like this:
bool equal = lst1.Count == lst2.Count && lst1.Count == lst1.Intersect(lst2).Count();
You can also use an IEqualityComparer<T>
with Intersect
.
Update:
It seems you want to be able to compare any object even if they don't implement IEquatable<T>
. Below is a sample of an equality comparer that will use IEquatable<T>
if it's available, Enumerable.SequenceEqual
if the type is a collection, and otherwise recursively check the public properties of the type using reflection:
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();
}
}
I didn't implement GetHashCode
because it is not needed by Enumerable.SequenceEqual
.
This should be able to do what you want (but be warned this is not exactly efficient; don't use this in performance critical code).
You will need to implement IEqualityComparer
for your objects and then use that in Union method
You might think of using reflection out here if you intended to compare two instances of any type BUT i am sure this is not the correct way , we are just taking advantage of framework.
as a hacked solution, you may see below code.
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;
}
Override Equals() and GetHashCode() methods in your Employee class
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
}
精彩评论