可重用的泛型相等比较器
在《可实现自动重载配置文件读取类》中,我用到了 EqualComparer 这个类用于比对字典中的键,应该有些人不了解,在这里我解释一下吧。
字典 Dictionary 的构造函数中,有一个是 Dictionary(IEqualityComparer<TKey> comparer) ,需要传入一个实现了 IEqualityComparer 接口的比较器,用于替换寻找 Key 时的默认 Equals 方法和 GetHashCode 方法。EqualComparer 可以说是一个通用的实现了 IEqualityComparer 接口的类吧,只是需要构造的时候传入一个对象比对的委托(最简单的是使用 Lambda 表达式)。我举个使用的例子:
attributes = new Dictionary<string, string>(new EqualComparer<string>((x, y) =>
string.Compare(x, y, StringComparison.CurrentCultureIgnoreCase) == 0));
当然不仅这里,所有需要用到 IEqualityComparer 接口实例的地方都可以这样用。另外一个比较常用的地方就是 LINQ 中的集合运算,可以参考这里的代码,我就不一一举例说明了。
下面,贴上我的实现代码,大家可以拷贝过去使用:
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Lenic.Core
{
/// <summary>
/// 一般相等比较器
/// </summary>
/// <typeparam name="T">任意类型</typeparam>
[DebuggerStepThrough]
public class EqualComparer<T> : IEqualityComparer<T>
{
/// <summary>
/// 获得当前相等比较器.
/// </summary>
/// <value>当前相等比较器. </value>
public Func<T, T, bool> Comparer { get; protected set; }
/// <summary>
/// 初始化新建一个 <see cref="EqualComparer<T>"/> 类的实例对象.
/// </summary>
/// <param name="comparer">一个相等比较器. </param>
public EqualComparer(Func<T, T, bool> comparer)
{
Comparer = comparer;
}
#region IEqualityComparer<T> 成员
/// <summary>
/// 确定指定的对象是否相等.
/// </summary>
/// <param name="x">要比较的第一个类型为 <paramref name="T"/> 的对象. </param>
/// <param name="y">要比较的第二个类型为 <paramref name="T"/> 的对象. </param>
/// <returns>如果指定的对象相等. 则为 true;否则为 false. </returns>
public bool Equals(T x, T y)
{
return Comparer(x, y);
}
/// <summary>
/// 返回此实例的哈希代码, 这里永远返回数字 0 .
/// </summary>
/// <param name="obj">待获得哈希代码的一个实例对象. </param>
/// <returns>32 位有符号整数哈希代码. </returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="obj"/> 的类型为引用类型. <paramref name="obj"/> 为 <c>null</c> . </exception>
public int GetHashCode(T obj)
{
return 0;
}
#endregion
#region IEqualityComparer<T> 成员
/// <summary>
/// 确定指定的对象是否相等。
/// </summary>
/// <param name="x">要比较的第一个类型为 <paramref name="T"/> 的对象。</param>
/// <param name="y">要比较的第二个类型为 <paramref name="T"/> 的对象。</param>
/// <returns>如果指定的对象相等,则为 true;否则为 false。</returns>
bool IEqualityComparer<T>.Equals(T x, T y)
{
return Equals(x, y);
}
/// <summary>
/// 返回此实例的哈希代码.
/// </summary>
/// <param name="obj">待获得哈希代码的一个实例对象.</param>
/// <returns>32 位有符号整数哈希代码.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="obj"/> 的类型为引用类型. <paramref name="obj"/> 为 <c>null</c> . </exception>
int IEqualityComparer<T>.GetHashCode(T obj)
{
return GetHashCode(obj);
}
#endregion
}
}