比较两个实例中的属性值

时间:2012-03-20 14:47:57

标签: c# .net reflection

我认为我有拳击问题

foreach(var p in item.GetType().GetProperties().
    Where(p => p.GetValue(original, null) is ValueType))
{
    var originalValue = p.GetValue(original, null);
    var modifiedValue = p.GetValue(item, null);
    if (!originalValue.Equals(modifiedValue)) 
        kvpData.AppendFormat("{0}={1}&", p.Name, originalValue);
}

originalValue永远不会等于modifiedValue,我猜它是因为它们被装在Object中。但是我该如何解决呢?

3 个答案:

答案 0 :(得分:1)

这不是拳击问题。 Equals是一个虚方法,盒装值类型覆盖得很好。

但是,我不确定问题是什么。可能是因为实际上没有匹配的属性吗?请注意,没有任何参数的GetProperties()只会返回公开属性。如果您需要的属性为私有,则需要添加一些BindingFlags

GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)

(我在这里假设您不需要静态属性。)

您是否也确定它实际上是属性,而不是字段?请记住,如果您将某些内容声明为

public string Name;

然后是字段,而

public string Name { get; set; }

属性。如果它实际上是您需要的字段,则需要使用GetFields()而不是GetProperties()使用相同的绑定标记。

答案 1 :(得分:0)

Linq是一个很棒的工具,但我不确定你为什么在这里使用它。你实际上导致这组属性被迭代两次,这是非常昂贵的。我会在没有Linq的情况下编写代码。此外,没有必要多次获得该值,这也是非常昂贵的。试试这段代码吧。它避免了我指出的缺陷,并且在我用它制作并测试了一个虚拟类时正确地进行了比较:

    foreach(PropertyInfo p in item.GetType().GetProperties())
    {
        if (p.PropertyType.BaseType == typeof(ValueType) || p.PropertyType == typeof(string))
        {
            var originalValue = p.GetValue(original, null);
            var modifiedValue = p.GetValue(item, null);
            if (originalValue != modifiedValue) kvpData.AppendFormat("{0}={1}&", p.Name, originalValue);
        }
     } 

另外,请注意字符串不是ValueType,尽管它们实现了值比较。

答案 2 :(得分:-1)

来自MSDN: Object.Equals

  

Equals的默认实现支持引用相等   引用类型和值类型的按位相等。参考   等于意味着被比较的对象引用引用   同一个对象。按位相等意味着被比较的对象具有   相同的二进制表示。

这意味着在您的情况下,这2个对象(如果它们是引用类型)永远不会指向同一个实例。

没有一种简单的方法可以像你想要的那样以通用的方式解决这个问题。

但是你可以在你要比较的那些类型上实现(只是一个例子)和IComparable,并且在这个迭代之后检查值rturned的类型是否实现了该接口,所以施放并调用它实现的IComparable.CompareTo方法。

你可以检查对象是否实现了指定的interfacce,在当前的IComparable中,你可以这样做:

originalValue .GetType().GetInterfaces().Any(x =>
  x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IComparable))

希望这有帮助。