如何调整泛型约束匹配HashSet的EqualityComparer<T>.Default要求?
问题原因
你遇到的ImmutableArray<T>测试失败问题,本质是ImmutableArray<T>的默认相等比较逻辑不符合你的预期:EqualityComparer<ImmutableArray<T>>.Default使用的比较逻辑是基于底层数组的引用相等,而非内容的结构相等。你两次调用ImmutableArray.Create生成的是底层数组不同的两个实例,默认比较会判定为不相等,所以HashSet的计数会变成2,和你的测试断言冲突。
方案1:调整泛型约束仅适配默认比较器逻辑
如果你就是要验证EqualityComparer<T>.Default的原生行为,只需要把原来的泛型约束里的struct限制去掉,就可以同时支持值类型和string这类符合默认比较预期的引用类型:
// 仅使用默认比较器的版本 bool IsDefaultHashEqual<T>(Func<T> f) where T : IEquatable<T> { var set = new HashSet<T>(); set.Add(f()); set.Add(f()); return set.Count == 1; }
这个版本下ImmutableArray<T>的测试返回false是符合预期的,因为默认比较器确实不会做结构相等判断。
方案2:自动识别需要结构相等的类型
如果你希望方法自动对支持结构相等的类型使用StructuralComparisons.StructuralEqualityComparer,可以在运行时判断类型是否实现了IStructuralEquatable接口,动态选择比较器,不需要额外的泛型约束:
bool IsHashEqual<T>(Func<T> f) { IEqualityComparer<T> comparer = typeof(IStructuralEquatable).IsAssignableFrom(typeof(T)) ? (IEqualityComparer<T>)StructuralComparisons.StructuralEqualityComparer : EqualityComparer<T>.Default; var set = new HashSet<T>(comparer); set.Add(f()); set.Add(f()); return set.Count == 1; }
这个版本会自动对数组、ImmutableArray<T>等实现了IStructuralEquatable的类型使用结构比较,其他类型沿用默认比较逻辑,你原来的基础类型、字符串测试都可以正常通过,ImmutableArray<T>的测试也会按内容相等返回true。
内容的提问来源于stack exchange,提问作者malat
相关产品推荐
相关产品推荐

