比较盒装值的行为不符合预期

时间:2015-05-04 20:58:33

标签: c#

我正在尝试比较两个不同Dictionary<string,object>内的对象(以查找版本化存储库中的差异。

字典可以包含任何序列化类型,值类型或引用类型。

我循环所有键以执行比较。由于值类型装箱,我实现了一个小实用程序方法found on SO

private static bool AreValueEquals(object o1, object o2)
{
    return (o1 != null && o1.GetType().IsValueType)
        ? o1.Equals(o2)
        : o1 == o2;
}

此方法在我的main方法中使用,如下所示:

private static List<string> GetDifferent(Dictionary<string, object> currentValues, Dictionary<string, object> previousValues)
{
    var changed = from fieldName in currentValues.Keys.Union(previousValues.Keys).Distinct()
                  let currentVal = GetIfExists(currentValues, fieldName)
                  let previousVal = GetIfExists(previousValues, fieldName)
                  where !AreValueEquals(currentVal, previousVal)
                  select fieldName;
    return changed.ToList();
}
private static object GetIfExists(Dictionary<string, object> values, string fieldName)
{
    return values.ContainsKey(fieldName) ? values[fieldName] : null;
}

虽然AreValueEquals方法按预期工作on my test case (dotnetfiddle),但在运行时,我得到意外结果:

result

我不明白这个结果。我的实施是否正确?怎么解决?

2 个答案:

答案 0 :(得分:1)

String是参考类型。

我不知道你是如何创建这些字符串的,但它们很可能表示为2个不同的字符串对象实例。

在你的方法中,你可以对2个物体进行==。默认情况下,只检查它们是否相同。

为什么不使用Generics并使用Comparer.Default或者只使用Equals()并使用null检查考虑你的拳击?

    object a = "d";
    object b = new String(new []{'d'});

    Console.Write("a == b: ");

    Console.WriteLine(a == b);

    Console.WriteLine("AreValueEquals: " + AreValueEquals(a,b));

    Console.WriteLine("Equals: " + a.Equals(b)); 

给出:

a == b: False
AreValueEquals: False
Equals: True

确认实习生:

    Console.WriteLine("\r\nComparing 2 constants\r\n");

    object c = "d";

    Console.Write("a == c: ");

    Console.WriteLine(a == c);

    Console.WriteLine("AreValueEquals: " + AreValueEquals(a,c));

    Console.WriteLine("Equals: " + a.Equals(c));    

给出:

Comparing 2 constants

a == c: True
AreValueEquals: True
Equals: True

看看这个fiddle

答案 1 :(得分:0)

我已经将GetDifferent方法更改为我认为您的目标:

private static List<string> GetDifferent(Dictionary<string, object> currentValues, Dictionary<string, object> previousValues)
{
    var changed = currentValues
                  .Where(k => previousValues.Any(p => p.Key == k.Key && !AreValueEquals(k.Value, p.Value)))
                  .Select(k => k.Key);
    return changed.ToList();
}

看到这个小提琴:https://dotnetfiddle.net/JZ6v6a

相关问题