Skip to content

Instantly share code, notes, and snippets.

@jeremybeavon
Created April 9, 2015 20:04
Show Gist options
  • Select an option

  • Save jeremybeavon/d8af10c21d09dad0b448 to your computer and use it in GitHub Desktop.

Select an option

Save jeremybeavon/d8af10c21d09dad0b448 to your computer and use it in GitHub Desktop.
LINQ EqualityComparer Extensions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace LinqEqualityComparerExtensions
{
public sealed class EqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, int> getHashCode;
private readonly Func<T, T, bool> equals;
public EqualityComparer(Func<T, int> getHashCode, Func<T, T, bool> equals)
{
if (getHashCode == null)
{
throw new ArgumentNullException("getHashCode");
}
if (equals == null)
{
throw new ArgumentNullException("equals");
}
this.getHashCode = getHashCode;
this.equals = equals;
}
public int GetHashCode(T obj)
{
return getHashCode(obj);
}
public bool Equals(T x, T y)
{
return equals(x, y);
}
}
public static class EnumerableExtensions
{
public static bool Contains<TSource>(
this IEnumerable<TSource> source,
TSource value,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return source.Contains(value, new EqualityComparer<TSource>(getHashCode, equals));
}
public static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return source.Distinct(new EqualityComparer<TSource>(getHashCode, equals));
}
public static IEnumerable<TSource> Except<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Except(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, elementSelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IEnumerable<TSource> Intersect<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Intersect(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static bool SequenceEqual<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.SequenceEqual(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToDictionary(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToDictionary(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToLookup(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToLookup(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IEnumerable<TSource> Union<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Union(second, new EqualityComparer<TSource>(getHashCode, equals));
}
}
public static class QueryableExtensions
{
public static bool Contains<TSource>(
this IQueryable<TSource> source,
TSource value,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return source.Contains(value, new EqualityComparer<TSource>(getHashCode, equals));
}
public static IQueryable<TSource> Distinct<TSource>(
this IQueryable<TSource> source,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return source.Distinct(new EqualityComparer<TSource>(getHashCode, equals));
}
public static IQueryable<TSource> Except<TSource>(
this IQueryable<TSource> first,
IQueryable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Except(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static IQueryable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IQueryable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
Expression<Func<TSource, TElement>> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IQueryable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
Expression<Func<TSource, TElement>> elementSelector,
Expression<Func<TKey, IEnumerable<TElement>, TResult>> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, elementSelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IQueryable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IQueryable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, IEnumerable<TInner>, TResult>> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IQueryable<TSource> Intersect<TSource>(
this IQueryable<TSource> first,
IQueryable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Intersect(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IQueryable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static bool SequenceEqual<TSource>(
this IQueryable<TSource> first,
IQueryable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.SequenceEqual(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
this IQueryable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToDictionary(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
this IQueryable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToDictionary(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
this IQueryable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToLookup(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
this IQueryable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToLookup(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static IQueryable<TSource> Union<TSource>(
this IQueryable<TSource> first,
IQueryable<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Union(second, new EqualityComparer<TSource>(getHashCode, equals));
}
}
public static class ParallelEnumerableExtensions
{
public static bool Contains<TSource>(
this ParallelQuery<TSource> source,
TSource value,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return source.Contains(value, new EqualityComparer<TSource>(getHashCode, equals));
}
public static ParallelQuery<TSource> Distinct<TSource>(
this ParallelQuery<TSource> source,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return source.Distinct(new EqualityComparer<TSource>(getHashCode, equals));
}
public static ParallelQuery<TSource> Except<TSource>(
this ParallelQuery<TSource> first,
ParallelQuery<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Except(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.GroupBy(keySelector, elementSelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
this ParallelQuery<TOuter> outer,
ParallelQuery<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ParallelQuery<TSource> Intersect<TSource>(
this ParallelQuery<TSource> first,
ParallelQuery<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Intersect(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
this ParallelQuery<TOuter> outer,
ParallelQuery<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static bool SequenceEqual<TSource>(
this ParallelQuery<TSource> first,
ParallelQuery<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.SequenceEqual(second, new EqualityComparer<TSource>(getHashCode, equals));
}
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToDictionary(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToDictionary(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToLookup(keySelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
this ParallelQuery<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, int> getHashCode,
Func<TKey, TKey, bool> equals)
{
return source.ToLookup(keySelector, elementSelector, new EqualityComparer<TKey>(getHashCode, equals));
}
public static ParallelQuery<TSource> Union<TSource>(
this ParallelQuery<TSource> first,
ParallelQuery<TSource> second,
Func<TSource, int> getHashCode,
Func<TSource, TSource, bool> equals)
{
return first.Union(second, new EqualityComparer<TSource>(getHashCode, equals));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment