比较对象的方法

Method to Compare objects

我正在开发一种方法,可以传入 2 个相同类型的对象,并将比较这两个对象。最后,我计划对其进行重载以接受 属性 名称等以仅评估那些或仅排除那些构成评估的名称。这将在我完成基本的完整比较工作后发生。

我已经能够比较值类型和引用类型。我卡住的地方是能够比较可枚举的属性。 else 语句是我无法正常工作的。

public static void CompareObjects<T>(T obj1, T obj2)
{
    foreach (var property in typeof(T).GetProperties())
    {
        var obj1Prop = property.GetValue(obj1);
        var obj2Prop = property.GetValue(obj2);

        //for value types
        if (property.PropertyType.IsPrimitive || property.PropertyType.IsValueType || property.PropertyType == typeof(string))
        {
            if (obj1Prop != obj2Prop)
                Console.WriteLine($"Object 1 {property.Name}:{obj1Prop}{Environment.NewLine}Object 2 {property.Name}:{obj2Prop}{Environment.NewLine}");
            }
            //for objects
            else if (property.PropertyType.IsClass && !typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
            {
                dynamic obj1PropObj = Convert.ChangeType(obj1Prop, property.PropertyType);
                dynamic obj2PropObj = Convert.ChangeType(obj2Prop, property.PropertyType);
                CompareObjects(obj1PropObj, obj2PropObj);
            }
            //for Enumerables
            else
            {
                var enumerablePropObj1 = property.GetValue(obj1) as IEnumerable;
                var enumerablePropObj2 = property.GetValue(obj2) as IEnumerable;

                if (enumerablePropObj1 == null) continue;
                if (enumerablePropObj2 == null) continue;

                var list1 = enumerablePropObj1.GetEnumerator();
                var list2 = enumerablePropObj2.GetEnumerator();

                while (list1.MoveNext())
                {
                    list2.MoveNext();
                    CompareObjects(list1.Current, list2.Current);
                }
            }
        }
    }

这遍历列表但没有值。我用来实现它的设置如下:

static void Main(string[] args)
{
    var student1 = new Student
    {
        FirstName = "John",
        LastName = "Smith",
        Age = 18,
        DateOfBirth = DateTime.Parse("1989/03/03"),
        Job = new Job
        {
            Company = "CompanyOne",
            Title = "Supervisor"
         },
         PhoneNumbers = new List<PhoneNumber>
         {
            new PhoneNumber
            {
                Number = "8675309",
                Label = "Home"
            },
            new PhoneNumber
            {
                Number = "1234567",
                Label = "Work"
            }
        }
    };
    var student2 = new Student
    {
        FirstName = "Theodore",
        LastName = "Smith",
        Age = 22,
        DateOfBirth = DateTime.Parse("1990/03/03"),
        Job = new Job
        {
            Company = "CompanyOne",
            Title = "Manager"
        },
        PhoneNumbers = new List<PhoneNumber>
        {
            new PhoneNumber
            {
                Number = "8675308",
                Label = "Home"
            },
            new PhoneNumber
            {
                Number = "1234567",
                Label = "Work"
            }
        }
    };

    CompareObjects(student1, student2);
    Console.WriteLine("Done");

    Console.ReadKey();
}

你的问题是你的方法是通用的。当您在子集合上调用它时,您用于比较的类型是 System.Object,当然没有可比较的有趣属性。

更改您的方法声明和方法的序言:

public static void CompareObjects(object obj1, object obj2)
{
    if (obj1.GetType() != obj2.GetType())
    {
        return;
    }

    foreach (var property in obj1.GetType().GetProperties())
    {
        ...

请注意,使用这种方法,您也不需要 dynamicChangeType() 代码。

最后,您可能需要考虑更改不等式比较,以便不使用 != 运算符,而是使用 Equals() 方法:

        if (!obj1Prop.Equals(obj2Prop))
        {
            Console.WriteLine($"Object 1 {property.Name}:{obj1Prop}{Environment.NewLine}Object 2 {property.Name}:{obj2Prop}{Environment.NewLine}");
        }

即使方法是通用的,那也是个好主意;虽然如果有人覆盖 应该 来实现相等和不等运算符 Equals(),但这种情况并不总是发生。当方法是非泛型时,当然你甚至不会得到特定类型的运算符重载(至少在没有大量额外工作的情况下)。


(我想你可以使用与上面相同的 dynamic/ChangeType() 方法来代替不可枚举的属性,使用例如 list1.Current.GetType() 作为类型而不是property.PropertyType; 这可以让该方法保持通用。但是 dynamic 有太多额外的开销,最终它会全部归结为执行相同的代码,我只是不明白其中的意义这样做。)