【问题标题】:How do I compare two objects' properties?如何比较两个对象的属性?
【发布时间】:2013-05-30 17:14:21
【问题描述】:

如何比较两个对象的属性以确定是否有任何属性发生了变化?我有一个带有一系列属性的Patient 对象。我有第二个对象UpdatedPatient,它可能有不同的值。目前,我对每个属性使用以下内容:

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

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

【问题讨论】:

  • 您可以从类似的问题中使用此示例。 stackoverflow.com/questions/957783/…
  • 上下文是什么?例如,许多框架和模式会让您实现 INotifyPropertyChanged 并订阅事件,如果您希望了解数据更改。当然,它并不能消除你的编码问题,但取决于你在做什么,也许你应该去探索它。

标签: c#


【解决方案1】:

是的,它有效,但我怀疑这是否是最有效的解决方案。

就运行时效率而言,这可能是最有效的解决方案。

检查所有属性后,如果 PatientChanged 标志为 true,则更新患者

如果你做空 curcuit,你可以加快这个速度 - 一旦检查了 any 属性并且PatientChangedtrue,你知道你需要更新,所以你可以跳过另一个检查。

当然,您可以使用Reflection 编写一个方法来为您执行此检查。但是,这在性能方面效率会低得多,但它可能无需为所有类型编写这些检查,这可以提高开发人员的效率。

【讨论】:

    【解决方案2】:

    我怀疑这是否是最有效的解决方案。

    答案取决于您衡量效率的方式。

    • 就 CPU 周期而言,这是最有效的方式
    • 在维护工作方面,基于反射的方法将被证明更有效。

    您可能希望构建一个混合 LINQ/Reflection 解决方案以获得可接受的效率并保持可维护性:使用反射来获取您需要比较的所有属性,构建一个 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));
    

    这是demo of this approach on ideone

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

    【讨论】:

      【解决方案3】:

      如果您将 exPt 设为结构而不是类,则其 .Equals 方法将比较每个字段,而不是引用比较。

      【讨论】:

      • 确实如此,但您通常不应该使用structs 的默认Equals(),因为它很慢(因为它使用反射)。
      • 是的。编写代码既快速又简单,但不一定要执行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      相关资源
      最近更新 更多