比较两个对象并返回差异

时间:2011-12-01 15:24:06

标签: c#

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

是否有“接受”的方式来做到这一点?

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>,而不是缩短比较。或者这只是我为获得额外信息而付出的代价?

5 个答案:

答案 0 :(得分:3)

也许你应该试试这个:

http://comparenetobjects.codeplex.com/

所有归功于作者......

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

答案 1 :(得分:1)

没有内置任何东西可以让你代表部分对象(即差异)。

你的方法对于你想要实现的目标似乎是合理的。

答案 2 :(得分:1)

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;
    }


}

答案 3 :(得分:0)

只要属性的名称相同,您就可以使用每个对象和linq的属性映射来完成此操作。我过去做过这个,但是我现在没有代码在我面前,抱歉。

答案 4 :(得分:0)

这是我用于单元测试同一对象类型的两个实例的示例。我正在测试以确保序列化为文件并在相同对象类型的新实例中填充的属性是相同的。请注意,这是使用System.Reflection,并且您正在比较相同类型的实例。

//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
                }
                    }
                }
            }