在stackoverflow上看到一个比较有意思的字典相等比较扩展方法,感觉思路比较巧妙,于是在这里转载下
PS:原方法不包含IEqualityComparer<TKey> keyComparer,此处将此问题补上
/// <summary>
/// 对象相等比较帮助类
/// </summary>
public static class EqualityComparerHelper
{
/// <summary>
/// 字典相等比较,原出处 http://stackoverflow.com/questions/3928822/comparing-2-dictionarystring-string-instances
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="first">用于比较的第一项</param>
/// <param name="second">用于比较的第二项</param>
/// <param name="keyComparer">当TKey为非基础数据类型,并且IDictionary在构造时未提供IEqualityComparer(SortedDictionary为IComparer),则该项必须不为null,否则比较结果必定为false</param>
/// <param name="valueComparer">当TValue为非基础数据类型时,该项必须不为null,否则比较结果必定为false</param>
/// <returns></returns>
public static bool DictionaryEqual<TKey, TValue>(
this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second,
IEqualityComparer<TKey> keyComparer = null, IEqualityComparer<TValue> valueComparer = null)
{
if (first == second) return true;
if (first == null || second == null) return false;
if (first.Count != second.Count) return false;
valueComparer = valueComparer ?? EqualityComparer<TValue>.Default;
if (keyComparer != null)
{//如果存在keyComparer,则重新构建字典
first = new Dictionary<TKey, TValue>(first, keyComparer);
second = new Dictionary<TKey, TValue>(second, keyComparer);
}
foreach (var kvp in first)
{
TValue secondValue;
if (!second.TryGetValue(kvp.Key, out secondValue)) return false;
if (!valueComparer.Equals(kvp.Value, secondValue)) return false;
}
return true;
}
}
对于实现IEqualityComparer的实现,在字典中需要注意GetHashCode的实现,即意义上相同的值其HashCode也应当一致
public class Person
{
public String FirstName { get; set; }
public String LastName { get; set; }
public int Age { get; set; }
}
public class PersonEqualityComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == y) return true;
if ((x == null) || (y == null)) return false;
return x.LastName == y.LastName;
}
public int GetHashCode(Person obj)
{
return obj.LastName.GetHashCode();
//return obj.GetHashCode() 在字典之类需要用到Hash值的地方不能这么写,会导致可以插入重复值
}
}
测试字典键值唯一性的代码
Dictionary<Person, int> dic = new Dictionary<Person, int>(new PersonEqualityComparer());
dic.Add(new Person { LastName = "Z", Age = 11 }, 10);
dic.Add(new Person { LastName = "Z", Age = 21 }, 15);//ArgumentException异常,已存在具有相同键的元素