I was wondering how I would find the difference between two objects of the same class. So if I had a Person class with the only difference being Age it will return the field/fields that are different.
Thanks
This isn't something that C# (or .NET really) supports directly, however you could implement something by hand for specific types, or write code that uses reflection to diff arbitrary objects.
If you choose the later, you will have to decide how deep you want to go into the object graph to identify whether two instances are identical or not and how you will compare certain primitive types for equality (doubles, for instance).
Writing a reflection-based differencing algorithm is more difficult that it seems at first - personally, I would implement this functionality directly for the types (or within a helper class) where you need it.
Here's some simple code I use for just such a thing while debugging:
//This structure represents the comparison of one member of an object to the corresponding member of another object.
public struct MemberComparison
{
public readonly MemberInfo Member; //Which member this Comparison compares
public readonly object Value1, Value2;//The values of each object's respective member
public MemberComparison(MemberInfo member, object value1, object value2)
{
Member = member;
Value1 = value1;
Value2 = value2;
}
public override string ToString()
{
return Member.Name + ": " + Value1.ToString() + (Value1.Equals(Value2) ? " == " : " != ") + Value2.ToString();
}
}
//This method can be used to get a list of MemberComparison values that represent the fields and/or properties that differ between the two objects.
public List<MemberComparison> ReflectiveCompare<T>(T x, T y)
{
List<MemberComparison> list = new List<MemberComparison>();//The list to be returned
foreach (MemberInfo m in typeof(T).GetMembers(BindingFlags.NonPublic | BindingFlags.Instance))
//Only look at fields and properties.
//This could be changed to include methods, but you'd have to get values to pass to the methods you want to compare
if (m.MemberType == MemberTypes.Field)
{
FieldInfo field = (FieldInfo)m;
var xValue = field.GetValue(x);
var yValue = field.GetValue(y);
if (!object.Equals(xValue, yValue))//Add a new comparison to the list if the value of the member defined on 'x' isn't equal to the value of the member defined on 'y'.
list.Add(new MemberComparison(field, yValue, xValue));
}
else if (m.MemberType == MemberTypes.Property)
{
var prop = (PropertyInfo)m;
if (prop.CanRead && prop.GetGetMethod().GetParameters().Length == 0)
{
var xValue = prop.GetValue(x, null);
var yValue = prop.GetValue(y, null);
if (!object.Equals(xValue, yValue))
list.Add(new MemberComparison(prop, xValue, yValue));
}
else//Ignore properties that aren't readable or are indexers
continue;
}
return list;
}
To use it, your code might look something like this:
public static void Main()
{
MyObject object1 = new MyObject();
MyObject object2 = new MyObject();
// ...Code that changes object1 and/or object2...
//Here's your answer: a list of what's different between the 2 objects, and each of their different values.
//No type parameters are needed here- typeof(MyObject) is implied by the coincident types of both parameters.
List<MemberComparison> changes = ReflectiveCompare(object1, object2);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With