我正在尝试编写一个比较对象的两个实例的属性的方法,这两个注意事项:1)对象通常会有其他复杂对象作为属性,甚至是其他复杂对象的数组,以及2)如果对象的一个实例上的属性为null,请不要担心对象的其他实例是否具有值。基本上,这样的事情(参见代码底部的预期结果):
public class Car
{
public string make { get; set; }
public string model { get; set; }
public Option[] options { get; set;}
public bool MagicCompare(Car obj)
{
// Do magic comparison
}
}
public class Option
{
public string name { get; set; }
public string value { get; set; }
}
Car c1 = new Car
{
make = "ford";
model = "F-150";
options = new[]
{
new Option {name = "seats", value = "leather"},
new Option {name = "radio", value = "XM"}
}
};
Car c2 = new Car
{
make = "ford";
model = "F-150";
};
Car c3 = new Car
{
make = "ford";
model = "mustang";
options = new[]
{
new Option {name = "seats", value = "leather"},
new Option {name = "radio", value = "XM"}
}
};
Car c4 = new Car
{
make = "ford";
model = "F-150";
options = new[]
{
new Option {name = "seats", value = "leather"}
}
};
c1.MagicCompare(c2); // would return true, since all non-null properties match
c1.MagicCompare(c3); // would return false, since all non-null properties do NOT match
c1.MagicCompare(c4); // would return false, since the options array doesn't match
答案 0 :(得分:0)
网上有很多针对C#的深度比较器实现。
此代码实现了一个处理几个字段或属性类型的代码,任何实现IEquatable
或ICollection
的代码。您需要添加其他类型,因为如果您有例如,它可能会爆炸自制的List
类型,未实施ICollection
。
public static class Ext {
public static bool HasDeclaredEquals(this object obj) =>
typeof(IEquatable<>).MakeGenericType(obj.GetType())
.IsAssignableFrom(obj.GetType());
}
public class JSONCollectionComparer : IEqualityComparer {
public new bool Equals(object x, object y) {
var c = new JSONComparer();
var xc = x as ICollection;
var yc = y as ICollection;
if (xc.Count != yc.Count)
return false;
var ans = true;
foreach (var xyv in xc.Cast<object>().Zip(yc.Cast<object>(), (xv, yv) => (xv, yv))) {
ans = ans && c.Equals(xyv.xv, xyv.yv);
if (!ans)
break;
}
return ans;
}
public int GetHashCode(object obj) {
throw new NotImplementedException();
}
}
public class JSONComparer : IEqualityComparer {
public new bool Equals(object x, object y) {
JSONComparer jc = null;
JSONCollectionComparer jac = null;
var ans = true;
var members = x.GetType().GetMembers().Where(m => m is PropertyInfo || m is FieldInfo);
foreach (var m in members) {
var mType = m.GetMemberType();
var xv = m.GetValue(x);
var yv = m.GetValue(y);
if (xv != null && yv != null)
if (xv.HasDeclaredEquals())
ans = ans && xv.Equals(yv);
else {
switch (xv) {
case ICollection xc:
jac = jac ?? new JSONCollectionComparer();
ans = ans && jac.Equals(xv, yv);
break;
default:
jc = jc ?? new JSONComparer();
ans = ans && jc.Equals(xv, yv); ;
break;
}
}
if (!ans)
break;
}
return ans;
}
public int GetHashCode(object obj) {
throw new NotImplementedException();
}
}
现在你的MagicCompare很简单:
public bool MagicCompare(Car obj) {
// Do magic comparison
return new JSONComparer().Equals(this, obj);
}