更新:从 C# 7.3 开始,这应该不再是问题。从发行说明:
当方法组包含一些类型参数不满足其约束的泛型方法时,这些成员将从候选集中删除。
C# 7.3 之前的版本:
所以我读了Eric Lippert 的 'Constraints are not part of the signature',现在我明白规范指定在重载决议之后检查类型约束,但我仍然不清楚为什么必须如此。下面是埃里克的例子:
static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main()
{
Foo(new Giraffe());
}
这不会编译,因为重载解析:Foo(new Giraffe())
推断这Foo<Giraffe>
是最佳重载匹配,但类型约束失败并引发编译时错误。用埃里克的话来说:
这里的原则是重载解析(和方法类型推断)在参数列表和每个候选方法的形式参数列表之间找到最佳匹配。也就是说,他们查看候选方法的签名。
类型约束不是签名的一部分,但为什么不能呢?在哪些情况下考虑将类型约束作为签名的一部分是一个坏主意?实施起来很难还是不可能?我并不是在主张,如果由于某种原因无法调用最佳选择的重载,那么就默默地回退到次优;我会讨厌那个。我只是想了解为什么不能使用类型约束来影响最佳重载的选择。
我在 C# 编译器内部想象,仅用于重载解析目的(它不会永久重写方法),如下:
static void Foo<T>(T t) where T : Reptile { }
转换为:
static void Foo(Reptile t) { }
为什么不能将类型约束“拉入”到形式参数列表中?这如何以任何不好的方式改变签名?我觉得它只会加强签名。然后Foo<Reptile>
永远不会被视为过载候选者。
编辑2:难怪我的问题如此混乱。我没有正确阅读 Eric 的博客,并且引用了错误的示例。我在我认为更合适的示例中进行了编辑。我还将标题更改为更具体。这个问题似乎不像我最初想象的那么简单,也许我错过了一些重要的概念。我不太确定这是 stackoverflow 材料,最好将此问题/讨论移到其他地方。