我有两个词典,两个都具有相同的结构和顺序(一个应该是另一个的精确复制品):Dictionary<int, ICustomInterface>
我想用SequenceEqual<>
<检查它们是否相等/ p>
首先,我将第一个字典转换为XML,然后将其读回以重新创建第二个字典。初步检查时,它们都是相同的。 ICustomeInterface
个对象各自正确覆盖Equals方法。为了检查这一点,我迭代了两个词典的元素并进行比较。他们都是平等的。
但是当我调用SequenceEqual
:dictionary1.SequenceEqual(dictionary2);
时,它返回false并且ICustomInterface
个对象的Equals方法永远不会被调用,它总是返回false。但是,如果我这样做:
for (i = 0; i < firstDictionary.Count; i++)
firstDictionary[i].SequenceEqual(otherSub.ItemSequence[i]);
一切都按预期工作,并且每行返回true。那么,当我简单地在字典本身上调用SequnceEqual时会发生什么?
答案 0 :(得分:16)
“正在发生什么”是按顺序比较两个词典的KeyValuePair
条目。字典本质上是无序的 - 你不应该依赖于条目从它们中出来的顺序。如果您使用:
firstDictionary.OrderBy(pair => pair.Key)
.SequenceEqual(secondDictionary.OrderBy(pair => pair.Key))
我怀疑你会发现那些比赛。虽然比较它们是一种非常不愉快的方式:)
答案 1 :(得分:1)
Jon Skeet已经给出了一个很好的解释。
但是,如果您(或其他任何阅读此问题的人)想要的是一种比较词典的有效方法,这是一个简单的基于Linq的扩展,它将做到这一点:
/// <summary>
/// Compares two dictionaries for equality.
/// </summary>
/// <returns>
/// True if the dictionaries have equal contents or are both null, otherwise false.
/// </returns>
public static bool DictionaryEqual<TKey, TValue>(
this IDictionary<TKey, TValue> dict1, IDictionary<TKey, TValue> dict2,
IEqualityComparer<TValue> equalityComparer = null)
{
if (dict1 == dict2)
return true;
if (dict1 == null | dict2 == null)
return false;
if (dict1.Count != dict2.Count)
return false;
if (equalityComparer == null)
equalityComparer = EqualityComparer<TValue>.Default;
return dict1.All(kvp =>
{
TValue value2;
return dict2.TryGetValue(kvp.Key, out value2)
&& equalityComparer.Equals(kvp.Value, value2);
});
}
它可能看起来有点蓬松,但我想要良好的可读性(和空测试)。
所以,如果你想要的只是一个&#34;单行&#34; ,你就已经知道这两个字典都是非空的,并且TValue
类型会覆盖等于方法正确,那么你真的需要这么多(如果TValue
当然是bool isEqual = dict1.Count == dict2.Count && dict1.All(kvp =>
{
TValue value2;
return dict2.TryGetValue(kvp.Key, out value2)
&& (kvp.Value == null ? value2 == null : kvp.Value.Equals(value2));
});
,则无空检查):
/// <summary>
/// Compares two dictionaries for equality using a custom value equality function.
/// </summary>
/// <returns>
/// True if both dictionaries are null or both have the same set of keys and comparing
/// their respective values for each key using the <paramref name="valueEqualityFunc"/>
/// returns true, otherwise false.
/// </returns>
public static bool DictionaryEqual<TKey, TValue1, TValue2>(
this IDictionary<TKey, TValue1> dict1, IDictionary<TKey, TValue2> dict2,
Func<TValue1, TValue2, bool> valueEqualityFunc)
{
if (valueEqualityFunc == null)
throw new ArgumentNullException("valueEqualityFunc");
if (dict1 == dict2)
return true;
if (dict1 == null | dict2 == null)
return false;
if (dict1.Count != dict2.Count)
return false;
return dict1.All(kvp =>
{
TValue2 value2;
return dict2.TryGetValue(kvp.Key, out value2)
&& valueEqualityFunc(kvp.Value, value2);
});
}
如果要进行比较,其中字典不必具有相同类型的值,或者如果您更喜欢使用委托或lambda表达式而不必实现IEqualityComparer,则此扩展将执行你的诀窍是:
var d1 = new Dictionary<string, string>();
var d2 = new Dictionary<string, string>();
d1.Add("key1", "dog");
d2.Add("key1", "Dog");
d1.Add("key2", "CAT");
d2.Add("key2", "cat");
bool isEqual = DictionaryEqual(d1, d2,
(s1, s2) => string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase));
你可以看到它和以前几乎一样。
以下是一个用法示例:
isEqual
如果您运行上面的代码text_en:(recreation -"create")
将成为现实。