目前,允许您自己定义相等比较的HashSet<T>
构造函数是HashSet<T>(IEqualityComparer<T> comparer)
构造函数。
我想将此EqualityComparer定义为lambda。
我发现this blog post创建了一个允许您通过lambda生成比较器的类,然后使用extention方法隐藏此类的构造,例如使用Except()。
现在我想用构造函数做同样的事情。是否可以通过扩展方法创建构造函数?或者是否有另一种方式我可以以某种方式创建HashSet<T>(Func<T,T,int> comparer)
?
- UPDATE -
为清楚起见,这是(我想要完成的徒手版本的一小部分):
HashSet<FileInfo> resultFiles = new HashSet<FileInfo>(
srcPath.GetFiles(),
new LambdaComparer<FileInfo>(
(f1, f2) => f1.Name.SubString(10).Equals(f2.Name.SubString(10))));
理想情况下或更多
HashSet<FileInfo> resultFiles = new HashSet<FileInfo>(
srcPath.GetFiles(),
(f1, f2) => f1.Name.SubString(10).Equals(f2.Name.SubString(10)));
答案 0 :(得分:5)
不,你不能添加构造函数(即使使用扩展方法)。
假设你有一些神奇的方式从Func<T,T,int>
到IEqualityComparer<T>
(如果你能引用它,我会有兴趣阅读那篇博文) - 那么你最接近的就是可能是这样的:
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);
}
}
然而;我怀疑你能用lambda做什么来实现平等......你有两个概念要表达:哈希和真正的平等。你的lambda会是什么样子?如果您尝试遵从子属性,那么可能需要Func<T,TValue>
来选择属性,并在内部使用EqualityComparer<TValue>.Default
...类似于:
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));
}
}
答案 1 :(得分:1)
这是我的妥协实施。它将允许任何通用的Func(就像Marc,我忽略了int,因为你没有解释它),并且这将给出正确的(因为它符合合同),但行为效率非常低。
我建议您坚持使用符合您需求的真正IEqualityComparer。遗憾的是,C#不支持匿名内部类。
public static class HashSetDelegate
{
public static HashSet<T> Create<T>(Func<T, T, bool> func)
{
return new HashSet<T>(new FuncIEqualityComparerAdapter<T>(func));
}
private class FuncIEqualityComparerAdapter<U> : IEqualityComparer<U>
{
private Func<U, U, bool> func;
public FuncIEqualityComparerAdapter(Func<U, U, bool> func)
{
this.func = func;
}
public bool Equals(U a, U b)
{
return func(a, b);
}
public int GetHashCode(U obj)
{
return 0;
}
}
}
public class HashSetTest
{
public static void Main()
{
HashSet<string> s = HashSetDelegate.Create((string a, string b) => string.Compare(a, b, true) == 0);
}
}