代码进行简单的分析:
DistinctBy
方法:
- 这个方法是一个泛型方法,参数包括
source
(要去重的源集合)和keySelector
(用于选择去重的键的委托)。 - 在方法内部,创建了一个
HashSet
对象seenKeys
,用于存储已经出现过的键。 - 遍历源集合中的每个元素,通过
keySelector
获取元素的键,并尝试将键加入到seenKeys
中。 - 如果成功加入(即之前没有出现过),则返回当前元素,实现去重的效果。
Distinct
方法:
- 这个方法也是一个泛型方法,参数包括
source
(要去重的源集合)和comparer
(用于比较元素是否相等的委托)。 - 在方法内部,调用了另一个重载的
Distinct
方法,并传入一个实现了IEqualityComparer<T>
接口的对象DynamicEqualityComparer<T>
。 DynamicEqualityComparer<T>
类实现了IEqualityComparer<T>
接口,根据传入的比较委托来判断两个元素是否相等。- 在
Equals
方法中,通过调用传入的比较委托来判断两个元素是否相等。 - 在
GetHashCode
方法中,简单地返回了固定的哈希码 0,因为在这里并不需要真正的哈希码。
/// <summary> /// list = list.Distinct(d => new { d.Age, d.Name }).ToList();/// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="source"></param> /// <param name="keySelector">p => new { p.ID, p.Name }</param> /// <returns></returns> public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector){HashSet<TKey> seenKeys = new HashSet<TKey>();foreach (TSource element in source){if (seenKeys.Add(keySelector(element))){yield return element;}}}/// <summary>/// 数据较大时使用此方法 list = list.Distinct((a, b) => a.Age == b.Age && a.Name == b.Name).ToList();/// </summary>/// <typeparam name="T"></typeparam>/// <param name="source"></param>/// <param name="comparer"></param>/// <returns></returns>public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer)where T : class=> source.Distinct(new DynamicEqualityComparer<T>(comparer));private sealed class DynamicEqualityComparer<T> : IEqualityComparer<T>where T : class{private readonly Func<T, T, bool> _func;public DynamicEqualityComparer(Func<T, T, bool> func){_func = func;}public bool Equals(T x, T y) => _func(x, y);public int GetHashCode(T obj) => 0;}