Lambda에 의해 정의 된 사용자 정의 iequalitycompare가있는 해시 세트 생성자?

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

문제

현재 HashSet<T> 평등 비교를 정의 할 수있는 생성자는 HashSet<T>(IEqualityComparer<T> comparer) 건설자. 나는이 평등을 람다로 정의하고 싶습니다.

나는 찾았다 이 블로그 게시물 이로 인해 Lambda를 통해 비교기를 생성 할 수있는 클래스가 만들어졌으며 예를 들어 ()을 예를 들어 연장 메소드 로이 클래스의 구성을 숨 깁니다.

이제 나는 똑같이하고 생성자와 함께하고 싶습니다. 확장 방법을 통해 생성자를 만들 수 있습니까? 아니면 어떻게 든 HashSet<T>(Func<T,T,int> comparer)?

--업데이트--
명확성을 위해, 이것은 내가 달성하려는 것의 프리 핸드 버전입니다.

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> an 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);
    }
}

하지만; 나는 당신이 평등을 위해 람다로 할 수있는 일에 대해 모호합니다 ... 당신은 표현할 두 가지 개념, 즉 해싱과 진정한 평등이 있습니다. 당신의 람다는 어떻게 생겼습니까? 아동 속성을 연기하려고한다면 아마도 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를 제공하면 잘못된 동작이 발생합니다.

내 타협 구현은 다음과 같습니다. 그것은 모든 일반적인 기능 (Marc와 같이 INT를 설명하지 않았기 때문에 INT를 무시 했음)을 허용하며, 이는 (계약을 준수한다는 점에서), 매우 비효율적 인 행동을 제공 할 것입니다.

귀하의 요구를 충족시키는 실제 iqualitycomparer를 고수하는 것이 좋습니다. 그러나 부끄러운 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