【问题标题】:How do I compare the fields/properties between POCOs? [duplicate]如何比较 POCO 之间的字段/属性? [复制]
【发布时间】:2010-12-11 19:03:03
【问题描述】:

可能重复:
Comparing object properties in c#

假设我有一个 POCO:

public class Person
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public IList<Person> Relatives { get; set; }
}

我想比较两个 Person 实例,看看它们是否相等。当然,我会比较 NameDateOfBirthRelatives 集合,看看它们是否相等。但是,这将涉及我为每个 POCO 覆盖 Equals() 并手动编写每个字段的比较。

我的问题是,我怎样才能编写一个通用版本,这样我就不必为每个 POCO 都这样做?

【问题讨论】:

    标签: c# generics properties comparison poco


    【解决方案1】:

    如果您不担心性能,可以在实用程序函数中使用反射来迭代每个字段并比较它们的值。

    using System; 
    using System.Reflection; 
    
    
    public static class ObjectHelper<t> 
    { 
        public static int Compare(T x, T y) 
        { 
            Type type = typeof(T); 
            var publicBinding = BindingFlags.DeclaredOnly | BindingFlags.Public;
            PropertyInfo[] properties = type.GetProperties(publicBinding); 
            FieldInfo[] fields = type.GetFields(publicBinding); 
            int compareValue = 0; 
    
    
            foreach (PropertyInfo property in properties) 
            { 
                IComparable valx = property.GetValue(x, null) as IComparable; 
                if (valx == null) 
                    continue; 
                object valy = property.GetValue(y, null); 
                compareValue = valx.CompareTo(valy); 
                if (compareValue != 0) 
                    return compareValue; 
            } 
            foreach (FieldInfo field in fields) 
            { 
                IComparable valx = field.GetValue(x) as IComparable; 
                if (valx == null) 
                    continue; 
                object valy = field.GetValue(y); 
                compareValue = valx.CompareTo(valy); 
                if (compareValue != 0) 
                    return compareValue; 
            } 
        return compareValue; 
        } 
    }
    

    【讨论】:

    • 嗯,我试了一下,但是propertiesfields 数组是空的。
    • 找出原因。删除 publicBinding 变量,或使用与 DeclaredOnly 或 Public 不同的枚举类型。
    • BindingFlags 允许您访问任何字段组合,公共或私有或静态等。很抱歉我的默认设置对您无效,但我很高兴您知道了!跨度>
    • 您可能还希望确保空值相等 替换:if (valx == null)    continue;    object valy = property.GetValue(y, null);  为:object valy = property.GetValue(y, null); if (valx == null &amp;&amp; valy == null) continue; if (valx == null) return -1;
    【解决方案2】:

    通常可以使用反射来执行此操作,但它具有性能和复杂性的缺点。手动实现EqualsGetHashCode 效果会好很多,这样你就能得到你期望的结果。

    Should I Overload == Operator?

    【讨论】:

      【解决方案3】:

      实现 Equals() 和 GetHashCode() 并不麻烦。

      public override bool Equals(object obj)
      {
          if (ReferenceEquals(this, obj) return true;
          if (!(obj is Person)) return false;
      
          var other = (Person) obj;
          return this == other;
      }
      
      public override int GetHashCode()
      {
          return base.GetHashCode();
      }
      

      Using Equals/GetHashCode Effectively

      【讨论】:

      • 我很困惑。您的示例只是 Equals() 的默认行为。对于一个类来说可能并不麻烦,但是当您需要将一堆样板代码添加到 50 多个类时,它确实变得很麻烦。
      猜你喜欢
      • 2015-02-26
      • 2021-10-13
      • 2017-02-26
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2014-06-29
      • 2012-07-05
      相关资源
      最近更新 更多