目前的 HashSet<T> 构造,让您来定义你的平等比较自己是 HashSet<T>(IEqualityComparer<T> comparer) 构造。我要定义这种EqualityComparer作为一个lambda。

我找到了 这篇文章 已经取得了一类,允许生成你的比较器通过lambda然后隐藏着建设的这类有一个延伸的方法来做例如,除了().

现在我想做同样的但有一个构造。是否有可能创建一个构造,通过一个延伸的方法?或是有另一种方式我可以以某种方式创建一个 HashSet<T>(Func<T,T,int> comparer)?

-更新--
为了清楚起见,这是(a段)手写版本,我想以完成的:

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)));
有帮助吗?

解决方案

不,你不能加入的构造(甚至扩展的方法)。

假设你有魔法的方式得到从 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看起来像什么?如果你试图推迟到儿童特性,那么也许是一个 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));
    }
}

其他提示

马克是正确的。有没有简单的方式为一个单一氧表达的信息所需的两个平等和GetHashCode.如果你提供一个GetHashCode返回不同的散列为"平等"的要素,这将造成错误的行为。

这是我的妥协的执行情况。它将允许任何通用的Func(如马克,我忽视的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);
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top