Currently the HashSet<T>
constructor that allows you to define your equality comparison yourself is the HashSet<T>(IEqualityComparer<T> comparer)
constructor.
I would like to define this EqualityComparer as a lambda.
I found this blog post that has made a class that allows you to generate your comparer through lambda and then hides the construction of this class with an extention method to do for example an Except().
Now I would like to do the same but with a constructor. Is it possible to create a constructor through an extention method? Or is there another way I could somehow create a HashSet<T>(Func<T,T,int> comparer)
?
--UPDATE--
For clarity, this is (a snippet of) a freehand version of what I'm trying to accomplish:
HashSet<FileInfo> resultFiles = new HashSet<FileInfo>(
srcPath.GetFiles(),
new LambdaComparer<FileInfo>(
(f1, f2) => f1.Name.SubString(10).Equals(f2.Name.SubString(10))));
or more ideally
HashSet<FileInfo> resultFiles = new HashSet<FileInfo>(
srcPath.GetFiles(),
(f1, f2) => f1.Name.SubString(10).Equals(f2.Name.SubString(10)));
No, you can't add constructors (even with extension methods).
Assuming you have some magic way to get from a Func<T,T,int>
to an IEqualityComparer<T>
(I'd be interested in reading that blog post if you can cite it) - then the closest you can do is probably something like:
public static class HashSet {
public static HashSet<T> Create<T>(Func<T, T, int> func) {
IEqualityComparer<T> comparer = YourMagicFunction(func);
return new HashSet<T>(comparer);
}
}
However; I'm dubious as to what you can do with a lambda for equality... you have two concepts to express: hashing, and true equality. What would your lambda look like? If you are trying to defer to child properties, then perhaps a Func<T,TValue>
to select the property, and use EqualityComparer<TValue>.Default
internally... something like:
class Person {
public string Name { get; set; }
static void Main() {
HashSet<Person> people = HashSetHelper<Person>.Create(p => p.Name);
people.Add(new Person { Name = "Fred" });
people.Add(new Person { Name = "Jo" });
people.Add(new Person { Name = "Fred" });
Console.WriteLine(people.Count);
}
}
public static class HashSetHelper<T> {
class Wrapper<TValue> : IEqualityComparer<T> {
private readonly Func<T, TValue> func;
private readonly IEqualityComparer<TValue> comparer;
public Wrapper(Func<T, TValue> func,
IEqualityComparer<TValue> comparer) {
this.func = func;
this.comparer = comparer ?? EqualityComparer<TValue>.Default;
}
public bool Equals(T x, T y) {
return comparer.Equals(func(x), func(y));
}
public int GetHashCode(T obj) {
return comparer.GetHashCode(func(obj));
}
}
public static HashSet<T> Create<TValue>(Func<T, TValue> func) {
return new HashSet<T>(new Wrapper<TValue>(func, null));
}
public static HashSet<T> Create<TValue>(Func<T, TValue> func,
IEqualityComparer<TValue> comparer)
{
return new HashSet<T>(new Wrapper<TValue>(func, comparer));
}
}