如何比较两个对象的属性?

5

我应该如何比较两个对象的属性,以确定是否有任何属性已更改?我有一个具有一系列属性的“患者”对象。我有第二个对象“UpdatedPatient”,可能具有不同的值。目前,我对每个属性使用以下方法:

if (exPt.Id!= pt.Id)
{
    exPt.Id = pt.Id;
    PatientChanged = true;
}

在检查所有属性之后,如果PatientChanged标志为true,则更新患者。是的,它可以工作,但我质疑这是否是最有效的解决方案。


你可以使用类似问题中的这个示例。https://dev59.com/fHNA5IYBdhLWcg3wcddk - Bearcat9425
2
什么是上下文?例如,许多框架和模式会要求您实现INotifyPropertyChanged并订阅事件,以便在数据更改时得到通知。当然,这并不能消除您的编码问题,但根据您正在做什么,也许您应该探索一下它。 - Anthony Pegram
3个回答

9

是的,它起作用了,但我在质疑这是否是最有效的解决方案。

从运行时间的效率角度来看,这很可能是最有效的解决方案。

在检查完所有属性之后,如果“PatientChanged”标志为真,则更新患者信息。

如果你使用短路方式,就可以加快速度-只要检查到任何一个属性并且“PatientChanged”为true,你就知道需要更新,所以可以跳过其他检查。

当然,你也可以使用Reflection编写一个方法来进行此检查。然而,从性能的角度来看,这会远没有那么高效,但它也许会消除必须为所有类型编写这些检查的需要,从而提高开发人员的效率。


5
我在思考这是否是最有效的解决方案。
答案取决于您衡量效率的方式。
- 从CPU周期的角度来看,这是最有效的方法。 - 从维护的角度来看,基于反射的方法会更加高效。
您可以构建一个混合的LINQ/反射解决方案,以获得可接受的效率并保持可维护性:使用反射获取所有需要比较的属性,构建一个LINQ表达式树逐个比较它们,将其编译为lambda,并使用所得到的函数对象进行CPU高效的比较。
以下是混合方法的示例实现:
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();
}

使用此方法,您可以执行以下类似的比较:
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));

这是一个关于IT技术的翻译内容:

这里有一个在ideone上的演示

请注意,此实现相当简单。它对所有属性使用 == ,而不是适当时使用 Equals 。您可以通过使第7行更加复杂来扩展它。


0
如果您将exPt定义为一个结构体而不是一个类,那么它的.Equals方法将会比较每个字段,而不是引用比较。

1
没错,但通常不应使用结构体的默认Equals(),因为它相当慢(因为它使用反射)。 - svick
真的。编码很快,很简单,但不一定执行起来就快。 - Deeko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接