比较两个对象并返回差异

本文关键字:返回 对象 两个 比较 | 更新日期: 2023-09-27 18:16:16

我必须在数千对对象之间运行比较,然后根据差异执行操作。

是否有一种"被接受"的方式来做这件事?

class ObjectA
{
    public string FieldA { get; set; }
    public string FieldB { get; set; }
    public string FieldC { get; set; }
}
class ObjectB
{
    public string FieldA { get; set; }
    public string FieldB { get; set; }
    public string FieldC { get; set; }
    public bool Equals(ObjectA obj)
    {
        if ((object)obj == null) return false;
        if (this.FieldA != obj.FieldA) return false;
        if (this.FieldB != obj.FieldB) return false;
        if (this.FieldC != obj.FieldC) return false;
        return true;            
    }
}
void test()
{
    ObjectA a = new ObjectA();
    ObjectB b = new ObjectB();
    if (b.Equals(a))
    {
         Console.WriteLine("Same!!");
    }
}

做了一个相当简单的测试来确定是否为b=a,但我也想知道它们之间有什么不同。

我应该添加一个返回属性列表的differences()方法吗?这似乎有点not.net,因为那时我将讨论字符串。

public List<string> Differences(ObjectA obj)
{
    List<string> differences = new List<string>();
    if ((object)obj == null)
    {
        differences.Add("null");
    }
    else
    {
        if (this.FieldA != obj.FieldA) differences.Add("FieldA");
        if (this.FieldB != obj.FieldB) differences.Add("FieldB");
        if (this.FieldC != obj.FieldC) differences.Add("FieldC");
    }
    return differences;
}

这似乎比第一个慢得多,因为我将创建所有这些List<string>,而不是缩短比较。或者这只是我获得额外信息的代价?

比较两个对象并返回差异

也许你应该试试这个:

http://comparenetobjects.codeplex.com/

一切归功于作者…

编辑:由于codeplex正在关闭,github url: https://github.com/GregFinzer/Compare-Net-Objects

没有任何内置功能允许您表示部分对象(即差异)。

你的方法似乎对你想达到的目标是合理的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class ObjectA
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
    public string PropertyC { get; set; }
    public DateTime PropertyD { get; set; }
    public string FieldA;
    public DateTime FieldB;
}
class ObjectB
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
    public string PropertyC { get; set; }
    public DateTime PropertyD { get; set; }

    public string FieldA;
    public DateTime FieldB;

}
class Program
{
    static void Main(string[] args)
    {
        // create two objects with same properties
        ObjectA a = new ObjectA() { PropertyA = "test", PropertyB = "test2", PropertyC = "test3" };
        ObjectB b = new ObjectB() { PropertyA = "test", PropertyB = "test2", PropertyC = "test3" };
        // add fields to those objects
        a.FieldA = "hello";
        b.FieldA = "Something differnt";
        if (a.ComparePropertiesTo(b))
        {
            Console.WriteLine("objects have the same properties");
        }
        else
        {
            Console.WriteLine("objects have diferent properties!");
        }

        if (a.CompareFieldsTo(b))
        {
            Console.WriteLine("objects have the same Fields");
        }
        else
        {
            Console.WriteLine("objects have diferent Fields!");
        }
        Console.Read();
    }
}
public static class Utilities
{
    public static bool ComparePropertiesTo(this Object a, Object b)
    {
        System.Reflection.PropertyInfo[] properties = a.GetType().GetProperties(); // get all the properties of object a
        foreach (var property in properties)
        {
            var propertyName = property.Name;
            var aValue = a.GetType().GetProperty(propertyName).GetValue(a, null);
            object bValue;
            try // try to get the same property from object b. maybe that property does
                // not exist! 
            {
                bValue = b.GetType().GetProperty(propertyName).GetValue(b, null);
            }
            catch
            {
                return false;
            }

            if (aValue == null && bValue == null)
              continue;
            if (aValue == null && bValue != null)
              return false;
            if (aValue != null && bValue == null)
              return false;
            // if properties do not match return false
            if (aValue.GetHashCode() != bValue.GetHashCode())
            {
                return false;
            }
        }
        return true;
    }

    public static bool CompareFieldsTo(this Object a, Object b)
    {
        System.Reflection.FieldInfo[] fields = a.GetType().GetFields(); // get all the properties of object a
        foreach (var field in fields)
        {
            var fieldName = field.Name;
            var aValue = a.GetType().GetField(fieldName).GetValue(a);
            object bValue;
            try // try to get the same property from object b. maybe that property does
            // not exist! 
            {
                bValue = b.GetType().GetField(fieldName).GetValue(b);
            }
            catch
            {
                return false;
            }
            if (aValue == null && bValue == null)
               continue;
            if (aValue == null && bValue != null)
               return false;
            if (aValue != null && bValue == null)
               return false;
            // if properties do not match return false
            if (aValue.GetHashCode() != bValue.GetHashCode())
            {
                return false;
            }
        }
        return true;
    }

}

下面是我用于单元测试相同对象类型的两个实例的示例。我正在进行测试,以确保序列化到文件并在相同对象类型的新实例中填充的属性是相同的。注意,这里使用的是System。反射和您正在比较相同类型的实例。

//Assume yourobjectA and yourobjectB have already been instantiated and populated.
//loop throught he properties and compare
//they should all be set the same as the previous instance
            PropertyInfo[] propertiesA = yourobjectA.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo[] propertiesB = yourobjectB.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            int count = oldProperties.Length;
            for (int i = 0; i < count; i++)
            {
                if ((propertiesA [i].CanRead) && (propertiesB [i].CanRead))
                {
                    if (propertiesA [i].PropertyType == typeof(String))
                    {
                        object oldStringValue = (string)propertiesA[i].GetValue(yourobjectA, null);
                        object newStringValue = (string)propertiesB[i].GetValue(yourobjectB., null);
                        if(oldStringValue != newStringValue )
                {
                //Do something
                }
                    }
                    if (propertiesA [i].PropertyType == typeof(Boolean))
                    {
                        object oldBoolValue = (bool)propertiesA [i].GetValue(yourobjectA, null);
                        object newBoolValue = (bool)propertiesB [i].GetValue(yourobjectB., null);
                        if(oldBoolValue != newBoolValue)
                {
                //Do something
                }
                    }
                }
            }

只要属性的名称相等,就可以使用每个对象和linq的属性映射来做到这一点。我以前也这样做过,但是现在我面前没有代码,抱歉。