/// <summary> /// 使用指定的 <see cref="IComparer{T}"/> 泛型接口,在排序 <see cref="IList{T}"/> 的某个元素范围中搜索键值。 /// </summary> /// <typeparam name="TElement">列表元素的类型。</typeparam> /// <typeparam name="TKey">要查找的键的类型。</typeparam> /// <param name="list">要搜索的从零开始的排序 <see cref="IList{T}"/>。</param> /// <param name="index">要搜索的范围的起始索引。</param> /// <param name="length">要搜索的范围的长度。</param> /// <param name="value">要搜索的键值。</param> /// <param name="keySelector">用于从元素中提取键的函数。</param> /// <param name="comparer">比较元素时要使用的 <see cref="IComparer{T}"/> 实现。</param> /// <returns>如果找到 <paramref name="value"/>,则为指定 <paramref name="list"/> /// 中的指定 <paramref name="value"/> 的索引。如果找不到 <paramref name="value"/> /// 且 <paramref name="value"/> 小于 <paramref name="list"/> 中的一个或多个元素, /// 则为一个负数,该负数是大于 <paramref name="value"/> 的第一个元素的索引的按位求补。 /// 如果找不到 <paramref name="value"/> 且 <paramref name="value"/> 大于 <paramref name="list"/> /// 中的任何元素,则为一个负数,该负数是(最后一个元素的索引加 1)的按位求补。</returns> /// <exception cref="InvalidOperationException"><paramref name="comparer"/> 为 <c>null</c>, /// 且 <typeparamref name="TKey"/> 类型没有实现 <see cref="IComparable{T}"/> 泛型接口。</exception> private static int BinarySearchInternal <TElement, TKey>(this IList <TElement> list, int index, int length, TKey value, Func <TElement, TKey> keySelector, IComparer <TKey> comparer) { Contract.Requires(list != null); Contract.Requires(keySelector != null); Contract.Requires(index >= 0 && index + length <= list.Count); Contract.Ensures((Contract.Result <int>() >= 0 && Contract.Result <int>() <= list.Count) || (Contract.Result <int>() < 0 && ~Contract.Result <int>() <= list.Count + 1)); if (comparer == null) { comparer = Comparer <TKey> .Default; } try { int low = index; int high = (index + length) - 1; while (low <= high) { int mid = low + ((high - low) >> 1); int cmp = comparer.Compare(keySelector(list[mid]), value); if (cmp == 0) { return(mid); } if (cmp < 0) { low = mid + 1; } else { high = mid - 1; } } return(~low); } catch (Exception ex) { throw CommonExceptions.ComparerFailed(ex); } }