这些通用类型在什么情况下会统一?

huangapple go评论100阅读模式
英文:

In what scenario do these generic types unify?

问题

C#编译器拒绝以下代码:

class A { }
class B { }

interface IInterface<T> { }

abstract class BaseType<T> : IInterface<T>, IInterface<B> where T : A { }

BaseType<T>上出现错误,错误信息为:

'BaseType<T>' 无法同时实现 'IInterface<T>' 和 'IInterface<B>',因为它们可能对某些类型参数的替换进行统一

当省略对T的类型约束,使其不必继承自A时,我可以理解为什么会出现问题,但是在有这个约束的情况下,一切应该都没问题,对吗?

我是否漏掉了某种情况,还是说这只是编译器无法确定这些类型是不相交的情况?

英文:

The C# compiler rejects the following code:

class A { }
class B { }

interface IInterface&lt;T&gt; { }

abstract class BaseType&lt;T&gt; : IInterface&lt;T&gt;, IInterface&lt;B&gt; where T : A { }

With an error on BaseType&lt;T&gt; saying:

> 'BaseType&lt;T&gt;' cannot implement both 'IInterface&lt;T&gt;' and 'IInterface&lt;B&gt;' because they may unify for some type parameter substitutions

When omitting the type constraint on T so that it does not have to inherit from A, I can see why this would be a problem, but with this constraint in place everything should be fine right?

Is there a scenario I am missing, or is this just a case of the compiler not figuring out that these types are disjoint?

答案1

得分: 2

这种行为在语言规范的18.6.3 实现接口的唯一性部分中有描述:

为了确定泛型类型声明的接口列表是否有效,执行以下步骤:

  • L 为在泛型类、结构或接口声明 C 中直接指定的接口列表。
  • L 中已有接口的基接口添加到 L 中。
  • L 中删除任何重复的接口。
  • 如果从 C 创建的任何可能的构造类型,在将类型参数替换为 L 后,导致 L 中的两个接口相同,则 C 的声明无效。在确定所有可能的构造类型时,不考虑约束声明

因此,这不是编译器无法解决某些问题,而是遵循规范。

请注意,在其他地方也会忽略泛型约束,例如在方法签名中(即泛型约束不是方法签名的一部分)。

英文:

This behavior is described in the 18.6.3 Uniqueness of implemented interfaces section of the language specification:

> To determine if the interface list of a generic type declaration is valid, the following steps are performed:

> - Let L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.
> - Add to L any base interfaces of the interfaces already in L.
> - Remove any duplicates from L.
> - If any possible constructed type created from C would, after type arguments are substituted into L, cause two interfaces in L to be identical, then the declaration of C is invalid. Constraint declarations are not considered when determining all possible constructed types.

So it is not about compiler not being able figuring something out but it following the spec.

Note that there are others places when the generic constraints are ignored - for example in method signatures (i.e. generic constraints are not part of the method signature).

huangapple
  • 本文由 发表于 2023年8月8日 20:56:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76859790.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定