具有不满意类型约束的通用方法是隐藏扩展方法[重复]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有不满意类型约束的通用方法是隐藏扩展方法[重复]相关的知识,希望对你有一定的参考价值。
这个问题在这里已有答案:
我正在使用一个整洁的小HashCode
实用程序与一些实例方法,有助于快速生成哈希值。我已经为这个问题简化了它,但它基本上是这样的:
public struct HashCode
{
private readonly int _hashCode;
public HashCode(int hashCode) { _hashCode = hashCode; }
override int GetHashCode() => _hashCode;
public static HashCode Start => new HashCode(17);
public HashCode Hash(int integer) => new HashCode(unchecked(integer + hashCode * 31));
public HashCode Hash<T>(T value) where T : struct => Hash(value.GetHashCode());
public HashCode Hash(string value) => Hash(value?.GetHashCode() ?? 17);
public HashCode Hash<T>(T? nullable) where T : struct =>
Hash(nullable?.GetHashCode() ?? 17);
// Other reference types, user must explicitly specify a comparer
public HashCode Hash<T>(T obj, IEqualityComparer<T> comparer) =>
Hash(obj == null ? 17: comparer.GetHashCode(obj));
public static implicit operator int(HashCode hashCode) => hashCode.GetHashCode();
}
允许光滑的哈希实现,如:
class Person {
// ...
override GetHashCode() => HashCode.Start.Hash(name).Hash(age).Hash(...);
}
正如您所看到的,它可以避免装箱等。如果您直接对参考类型进行哈希处理,则必须指定一个比较器以确保您知道它是如何进行哈希处理的。似乎合理
现在,我希望在我的一个项目中添加一些扩展方法(即不重复和修改库),这样我就可以轻松地添加一些我自己经常使用的类型的consice哈希函数,并使用完全相同的语法来使用它们:
public static class HashCode_Extensions
{
public static HashCode Hash(this HashCode hc, DateRange range) =>
hc.Hash(range?.begin).Hash(range?.end);
public static HashCode Hash(this HashCode hc, IEnumerable<T> list) where T : struct =>
list.Aggregate(hc, (hc, elem) => hc.Hash(elem));
// etc...
}
我以为我太聪明了,大量的复制粘贴代码就会消失。
class Meeting {
// ...
override GetHashCode() => HashCode.Start.Hash(name).Hash(dateRange).Hash(invitees);
}
不幸的是,编译器正在选择我自己的通用实例方法,即使我的方法是完美的,而泛型方法的类型约束不是
CS0453类型'DateRange'必须是不可为空的值类型,以便在泛型类型的方法'HashCode.Hash(T)'中将其用作参数'T'
显然,编译器已经确定Hash
的“最佳重载”是具有非满足泛型类型约束的那个。太糟糕了,因为我的扩展方法非常适合。
有没有什么办法可以欺骗编译器使用正确的方法,而不必诉诸于使用不同的函数名称或在我调用Hash
时包含'虚拟'参数?
我也很高兴如果有一些向后兼容的方式让我改变HashCode
库,这将允许我的扩展方法被注意到。 (我不想将自定义重载添加到基本库,因为这些自定义类型当前不存在于其命名空间中)
一个小技巧将起作用。创建一个这样的类:
public class RequireStruct<T> where T : struct { }
将其作为可选参数放在泛型方法中,如下所示:
public struct HashCode
{
private readonly int _hashCode;
public HashCode Hash<T>(T value, RequireStruct<T> ignore = null) where T : struct => Hash(value.GetHashCode());
}
现在当你这样做时,它会像你想要的那样选择你的扩展方法:
HashCode code = new HashCode();
code.Hash(new DateRange());
从here偷来的。
以上是关于具有不满意类型约束的通用方法是隐藏扩展方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript:相当于 C# 的用于扩展类的通用类型约束?
为啥我会收到错误“协议……只能用作通用约束,因为它具有自身或关联的类型要求”?