HashSetのコンストラクタとカスタムIEqualityCompareで定義されるラムダ?

StackOverflow https://stackoverflow.com/questions/881438

質問

現在の HashSet<T> コンストラクタで定義する等号比較の自分自身の HashSet<T>(IEqualityComparer<T> comparer) コンストラクタです。いを定義するこEqualityComparerとしてラムダ.

このブログ なるかもしれないが、それ以外はできるようにするクラスでごcomparerを通じてラムダを隠の建設がこのクラスを拡張方法などを除く().

においても同様ですが、コンストラクタです。を作成できるコンストラクタにより拡張できますか?はしおりを付けることができっこなんだかを 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)));
役に立ちましたか?

解決

いいえ、できない追加のコンストラクタでも延長できません。

といってもマジック取得ら 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);
    }
}

しかし;私は疑わしいとしてよくお使いいただくために、ラムダ等...い二つのコンセプトエクスプレス:ハッシュ、trueを進めていきます。うさ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));
    }
}

他のヒント

Marcについてはその通りである。ありません簡単に単一のラムダを表現するのに必要な情報の両方のEqualsおよび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