C# 复杂类实例的相等判断
阅读原文时间:2023年07月09日阅读:3

在比较两个对象是否完全相同时,对于string, int等其他value object,可以直接通过“==”或者“Equals”来进行判断。但是对于复杂类,如下的Student类,则需要比较每个属性的值是否相同。并且在Student类中还涉及到了列表的对比问题。

public class Student
{
public string Name { get; set; }
public List

Addresses { get; set; }
public Parent Parent { get; set; }
}

public class Address
{
public string Country { get; set; }
public string Province { get; set; }
public string City { get; set; }
public string District { get; set; }
public int Number { get; set; }
}

public class Parent  
{  
    public string Mom { get; set; }  
    public string Dad { get; set; }  
}

为了不需要对属性进行一个个的对比,参考网上的各种博客,写了下面的一段代码。(个人感觉这个方法肯定不是最好的,而且解决的问题有限,希望大家能告诉我更好的方法,谢谢。)

static bool CheckEqual(T first, T second, Type type)
{
if (first == null && second == null)
return true;
else if (first == null || second == null)
return false;

        // 利用反射获取类型的全部属性  
        PropertyInfo\[\] properties = type.GetProperties();

        foreach(var property in properties)  
        {  
            // 首先判断该属性是否为值对象,即int,double,以及string类  
            if (CheckValueObject(property.PropertyType))  
            {  
                // 属性属于值对象和string类的话,则直接使用Equals对两个值进行比较  
                if (!property.GetValue(first).Equals(property.GetValue(second)))  
                {  
                    Console.WriteLine(type.Name + "." + property.PropertyType.Name + " is different");  
                    return false;  
                }  
            }  
            else  
            {  
                // 属性不属于值对象和string类,且属性是列表。这里已知列表是Address类型的列表  
                if (property.PropertyType.ToString().Contains("List"))  
                {  
                    List<Address> item1 = (List<Address>)property.GetValue(first);  
                    List<Address> item2 = (List<Address>)property.GetValue(second);  
                    // 对列表进行比较  
                    if (!CheckListEqual(item1, item2))  
                    {  
                        Console.WriteLine("Addresses are different");  
                        return false;  
                    }  
                }  
                else  
                {  
                    // 属性不属于值对象且不是列表,则递归  
                    return CheckEqual(property.GetValue(first), property.GetValue(second),property.PropertyType);  
                }  
            }  
        }  
        return true;  
    }

    static bool CheckValueObject(Type t)  
    {  
        if (t.IsValueType)  
            return true;  
        else if (t.FullName == typeof(String).FullName)  
            return true;  
        else  
            return false;  
    }

    // 关于列表的对比。  
    static bool CheckListEqual(List<Address>first, List<Address> second)  
    {  
        if (first == null && second == null)  
            return true;  
        else if (first == null || second == null)  
            return false;  
        // 首先判断两个列表的长度  
        else if (first.Count != second.Count)  
            return false;  
        else  
        {  
            // 先将两个列表按照Country属性进行排序  
            List<Address> \_first = first.OrderBy(x => x.Country).ToList();  
            List<Address> \_second = second.OrderBy(x => x.Country).ToList();  
            // 逐一比较每个元素,如果有不一样的,则返回false  
            for (int i = 0; i < \_first.Count; i++)  
            {  
                if(!CheckEqual(\_first\[i\],\_second\[i\], typeof(Address)))  
                {  
                    return false;  
                }  
            }  
            return true;  
        }

    }

Test:

static void Main(string[] args)
{
Address address1 = new Address()
{
Country = "China",
Province = "Guangdong",
City = "Shenzhen",
District = "Nanshan",
Number = 1
};
Address address2 = new Address()
{
Country = "China",
Province = "Guangdong",
City = "Shenzhen",
District = "Nanshan",
Number = 2
};
Address address3 = new Address()
{
Country = "China",
Province = "Guangdong",
City = "Guangzhou",
District = "Huadu",
Number = 1
};

        Parent parent1 = new Parent()  
        {  
            Mom = "Lily",  
            Dad = "Tom"  
        };  
        Parent parent2 = new Parent()  
        {  
            Mom = "Lucy",  
            Dad = "Jack"  
        };  
        Student student1 = new Student()  
        {  
            Name = "Spencer",  
            Parent = parent1,  
            Addresses = new List<Address>() { address1, address2 }  
        };

        Student student2 = new Student()  
        {  
            Name = "Spencer",  
            Parent = parent1,  
            Addresses = new List<Address>() { address1, address3 }  
        };

        Student student3 = new Student()  
        {  
            Name = "Spencer",  
            Parent = parent1,  
            Addresses = new List<Address>() { address1, address3 }  
        };

        Student student4 = new Student()  
        {  
            Name = "Spencer",  
            Parent = parent2,  
            Addresses = new List<Address>() { address1, address2 }  
        };

        Console.WriteLine(CheckEqual(student1, student4, typeof(Student)));

        Console.Read();  
    }