How do I compare the properties of two objects to determine if any properties have changed? I have a Patient
object with a series of properties. I have a second object, UpdatedPatient
, that may have different values. Currently, I'm using the following for each property:
if (exPt.Id!= pt.Id)
{
exPt.Id = pt.Id;
PatientChanged = true;
}
After all the properties are checked, if the PatientChanged
flag is true
, the patient is updated. Yes, it works but I'm questioning if this if the most efficient solution.
Yes, it works but I'm questioning if this if the most efficient solution.
This is likely the most efficient solution in terms of runtime efficiency.
After all the properties are checked, if the PatientChanged flag is true, the patient is updated
You could speed this up if you short curcuit - as soon as any property is checked and the PatientChanged
is true
, you know you need to update, so you could skip the other checks.
You could, of course, use Reflection to write a method to do this check for you. However, this would be far less efficient in terms of performance, but it might eliminate having to write these checks for all of your types, which could improve developer efficiency.
I'm questioning if this if the most efficient solution.
The answer depends on the way in which you are measuring the efficiency.
You may want to built a hybrid LINQ/Reflection solution to get acceptable efficiency and keep maintainability in place: use reflection to get all your properties that you need to compare, build a LINQ expression tree that compares them one by one, compile it as a lambda, and use the resultant functor for CPU-efficient comparisons.
Here is a sample implementation of the hybrid approach:
public static Func<T,T,bool> MakeComparator<T>() {
var lhs = Expression.Parameter(typeof (T));
var rhs = Expression.Parameter(typeof (T));
var allPropChecks = typeof(T)
.GetProperties()
.Where(p => p.CanRead && p.GetIndexParameters().Length == 0)
.Select(p => Expression.Equal(Expression.Property(lhs, p), Expression.Property(rhs, p)))
.ToList();
Expression compare;
if (allPropChecks.Count == 0) {
return (a,b) => true; // Objects with no properties are the same
} else {
compare = allPropChecks[0];
compare = allPropChecks
.Skip(1)
.Aggregate(compare, Expression.AndAlso);
}
return (Func<T, T, bool>)Expression.Lambda(compare, new[] { lhs, rhs }).Compile();
}
With this method in hand, you can perform comparisons like this:
class Point3D {
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
}
...
// Construct sample objects
var p1 = new Point3D { X = 1, Y = 2, Z = 3};
var p2 = new Point3D { X = 1, Y = 2, Z = 3 };
var p3 = new Point3D { X = 1, Y = 3, Z = 1 };
// Get a comparator
var cmp = MakeComparator<Point3D>();
// Use the comparator to compare objects to each other
Console.WriteLine(cmp(p1, p2));
Console.WriteLine(cmp(p2, p3));
Here is a demo of this approach on ideone.
Note that this implementation is rather simplistic. It uses ==
for all attributes, rather than going for Equals
where appropriate. You can expand upon it by making line 7 more sophisticated.
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