【问题标题】:Compare 2 object of the same class比较同一类的 2 个对象
【发布时间】:2015-08-06 14:25:18
【问题描述】:

最近,我遇到了在 C# 中比较同一类的 2 个对象的问题。我需要知道更改了哪些字段/属性。

示例如下:

SampleClass 
{
  string sampleField1;
  int sampleField2;
  CustomClass sampleField3; 
}

例如,我有 2 个SampleClass 对象,object1object2。 这两个对象有一些不同的字段值。

  • 谁能知道获取哪些字段不同的最佳方法?

  • 以及如何获取不同字段/属性的(字符串)名称?

  • 我听说过 .Net 中的反射。这是在这种情况下最好的方法吗?
  • 如果我们没有 CustomClass 字段呢? (我只是将此字段用于更通用的方法,在我的情况下该字段不存在)

【问题讨论】:

  • 在一般情况下:有办法通过反射或元编程来做到这一点,但没有内置
  • 这是一个奇怪的要求。好吧,你为什么不喜欢if(object1.sampleField1 != object2.sampleField1) { ... }
  • 感谢您提供信息@Marc Gravell :)
  • 谢谢拉胡尔,我需要得到不同的值的字符串名称。

标签: c# compare


【解决方案1】:

如果你想要通用的方式来获取所有更改的属性

你可以使用这个方法(而且它正在使用反射^_^)

    public List<string> GetChangedProperties(object obj1, object obj2)
    {
        List<string> result = new List<string>();

        if(obj1 == null || obj2 == null )
            // just return empty result
            return result;

        if (obj1.GetType() != obj2.GetType())
            throw new InvalidOperationException("Two objects should be from the same type");

        Type objectType = obj1.GetType();
          // check if the objects are primitive types
        if (objectType.IsPrimitive || objectType == typeof(Decimal) || objectType == typeof(String) )
            {
                // here we shouldn't get properties because its just   primitive :)
                if (!object.Equals(obj1, obj2))
                    result.Add("Value");
                return result;
            }

        var properties = objectType.GetProperties();

        foreach (var property in properties)
        {
            if (!object.Equals(property.GetValue(obj1), property.GetValue(obj2)))
            {
                result.Add(property.Name);
            }
        }

        return result;

    }

请注意,此方法仅获取已更改的Primitive type properties 并引用引用同一实例的类型属性

编辑: 如果obj1obj2 是原始类型(int,string ...),则添加了验证,因为我尝试传递字符串对象,它会给出错误 还修复了检查两个值是否为equal的bug

【讨论】:

  • 我认为您应该在值之前测试类型以更安全
  • 感谢@Bakri Bitar您非常干净易懂的回答,我真的很喜欢您使用情感的方式^_^我现在下班了,明天我会试试你的方式。这看起来是一个很有前途的解决方案。再次感谢您,
  • 我实际上不认为这适用于字符串类型属性以外的任何东西。
  • 这应该适用于任何值类型和任何实现 Equals 的类
  • @Paradise228 否,因为GetValue 返回一个对象,因此任何原始类型都不会引用同一个对象。字符串之所以有效,是因为它们的工作方式。
【解决方案2】:

对此处发布的另一个答案稍作修改,但此答案适用于非 string 类型的属性,不使用内部列表并自动进行一些初步类型检查,因为它是通用的:

public IEnumerable<string> ChangedFields<T>(T first, T second)
{
    if (obj1.GetType() != obj2.GetType())
        throw new ArgumentOutOfRangeException("Objects should be of the same type");

    var properties = first
        .GetType()
        .GetProperties();

    foreach (var property in properties)
    {
        if(!object.Equals(property.GetValue(first), property.GetValue(second)))
        {
            yield return property.Name;
        }
    }
}

【讨论】:

  • 非常感谢@DavidG
【解决方案3】:

如果您需要比较两个对象作为业务逻辑反射的一部分,那么您可以这样做,除非您当然可以为每种类型编写比较器类。

如果您想在调试期间在运行时比较两个对象,有一个名为 Oz Code 的简洁插件可以为您做到这一点,如下所示:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多