【问题标题】:HashSet: Infer the correct EqualityComparer<T>.Default? [duplicate]HashSet:推断正确的 EqualityComparer<T>.Default? [复制]
【发布时间】:2021-09-23 17:07:23
【问题描述】:

让我们考虑以下简单的实现来检查一个类型是否具有正确的 HashSet EqualityComparer&lt;T&gt;.Default 实现:

bool IsHashEqual<T>(Func<T> f) where T : struct, IEquatable<T>
{
    var set = new HashSet<T>();
    set.Add(f());
    set.Add(f());
    return set.Count == 1;
}

我们可以验证以下内容:

Assert.True(IsHashEqual(() => 42));
Assert.True(IsHashEqual(() => 3.14));
Assert.True(IsHashEqual(() => true));

通过一些工作,我们可以扩展上面的IsHashEqual 代码并在string 类上验证此属性。

但是我们可以让上面的代码失败,比如:

Assert.False(IsHashEqual(() => ImmutableArray.Create(new byte[] { 0, 1, 2, 3 })));

如何修改我的通用约束,使其符合默认相等比较器 (EqualityComparer&lt;T&gt;.Default) 的期望?否则我可以从T 类型推断出我需要使用StructuralComparisons.StructuralEqualityComparer 吗?

参考资料:

【问题讨论】:

    标签: c# generics set


    【解决方案1】:

    默认相等比较器检查类型 T 是否实现了 System.IEquatable 接口,如果是,则返回使用该实现的 EqualityComparer。

    IsHashEqual(() =&gt; ImmutableArray.Create(new byte[] { 0, 1, 2, 3 })) 返回 false,因为 ImmutableArray 中方法 Equals 的实现只是比较内部数组的引用。

    如果您希望 HashSet 按值比较数组,则需要编写自己的 IEqualityComparer 实现:

    class ImmutableArrayComparer<T> : IEqualityComparer<ImmutableArray<T>>
    {
        public bool Equals([AllowNull] ImmutableArray<T> first, [AllowNull] ImmutableArray<T> second)
        {
            return StructuralComparisons.StructuralEqualityComparer.Equals(first, second);
        }
    
        public int GetHashCode([DisallowNull] ImmutableArray<T> array)
        {
            return StructuralComparisons.StructuralEqualityComparer.GetHashCode(array);
        }
    }
    

    现在“naive”实现按预期工作并返回 true:

    bool IsImmutableHashEqual<T>(Func<ImmutableArray<T>> f)
    {
        var set = new HashSet<ImmutableArray<T>>(new ImmutableArrayComparer<T>());
        set.Add(f());
        set.Add(f());
        return set.Count == 1;
    }
    

    但请记住,如果您在 HasSet 中有很多大型数组,您可能会遇到性能问题。

    【讨论】:

    • 问题仍然存在,我不知道如何根据输入类型实例化 right HashSet。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 2011-08-08
    • 1970-01-01
    • 2016-03-15
    • 2020-08-04
    相关资源
    最近更新 更多