比较对象的方法
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())
{
...
请注意,使用这种方法,您也不需要 dynamic
和 ChangeType()
代码。
最后,您可能需要考虑更改不等式比较,以便不使用 !=
运算符,而是使用 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
有太多额外的开销,最终它会全部归结为执行相同的代码,我只是不明白其中的意义这样做。)
我正在开发一种方法,可以传入 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())
{
...
请注意,使用这种方法,您也不需要 dynamic
和 ChangeType()
代码。
最后,您可能需要考虑更改不等式比较,以便不使用 !=
运算符,而是使用 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
有太多额外的开销,最终它会全部归结为执行相同的代码,我只是不明白其中的意义这样做。)