可重用的泛型相等比较器

在《可实现自动重载配置文件读取类》中,我用到了 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&lt;T&gt;"/> 类的实例对象. 
        /// </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
    }
}
posted @ 2011-12-04 13:31  Lenic  阅读(1274)  评论(1编辑  收藏  举报