比较两个实例中属性的值

本文关键字:属性 实例 两个 比较 | 更新日期: 2023-09-27 18:28:27

我想我有装箱问题

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中。但是我该怎么解决呢?

比较两个实例中属性的值

这不是装箱问题。Equals是一个虚拟方法,装箱的值类型可以很好地覆盖它。

然而,我不确定问题是什么。可能是实际上没有任何匹配的属性吗?请记住,不带任何参数的GetProperties()将只返回公共属性。如果您需要的属性是私有,则需要添加一些BindingFlags:

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

(我在这里假设你不想要静态属性。)

您是否还确定您追求的实际上是属性,而不是字段?请记住,如果您将某些东西声明为

public string Name;

则它是字段,而

public string Name { get; set; }

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

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,尽管它们确实实现了值比较。

来自MSDN:Object.Equals:

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

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

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

但是,您可以在要比较的类型上实现(只是一个例子)一个IComparable,然后在本次迭代中检查rtured值的类型是否实现了该接口,因此强制转换并调用它的已实现IComparable.CompareTo方法。

您可以检查对象是否实现了指定的interacce,在当前的情况下是IComparable,您可以执行以下操作:

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

希望这能有所帮助。