在比较两个对象是否完全相同时,对于string, int等其他value object,可以直接通过“==”或者“Equals”来进行判断。但是对于复杂类,如下的Student类,则需要比较每个属性的值是否相同。并且在Student类中还涉及到了列表的对比问题。
public class Student { public string Name { get; set; } public List<Address> 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>(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(); }