类型X不能用作通用类型Y中的类型参数T

时间:2019-01-20 18:47:06

标签: c# .net generics interface covariance

我看不到以下代码有什么问题,或者如何解决。 (也许我误解了泛型类型。)

# works great
struct0['val'] + struct1['val']

编译器抱怨无法在通用类型class X<I> where I : ISomeInterface { } class Y<T> where T : X<ISomeInterface> { } class Z<I> where I : ISomeInterface { Y<X<I>> AData { get; } // What compiler does not like Y<X<ISomeInterface>> BData { get; } // What compiler likes } 中将X<I>用作类型参数T

1 个答案:

答案 0 :(得分:4)

这里是working solution

interface ISomeInterface {}

class X<I>
   where I : ISomeInterface
{ }

class Y<T, I>
   where T : X<I>
   where I : ISomeInterface
{ }

class Z<I>
   where I : ISomeInterface
{
   Y<X<I>, I> MyOtherData { get; set; }
   Y<X<ISomeInterface>, ISomeInterface> MyData { get; set; }
}

请注意,我在类型I的定义中添加了附加的通用参数Y和约束。

您对Y的初始定义过于严格。 C#使ISomeInterface与实现ISomeInterface的任何类型有所不同。

为什么会这样?

.NET编译器具有处理通用类型的特殊方式。对于每种泛型类型,编译器将基于泛型类型参数创建一个单独的类型,该类型将在运行时使用。例如,List<int>List<string>将是完全不同的类型,都表现出List<_>泛型类型定义的行为,但实际类型为intstring嵌入到编译器生成的具体类型中。

定义class Y<T> where T : X<ISomeInterface>时,会将“ X”的通用参数“密封”为ISomeInterface。即使X<ISomeInterface>本身是X<SomethingElse>的实现,编译器也可以接受继承SomethingElse但不继承ISomeInterface的任何类型。这是因为片段where T : X<ISomeInterface>导致ISomeInterface被放入Y<T>的类型定义中。这种行为是预期的,并且是将泛型编译为实际代码的副作用。由于相同的原因,无法执行以下操作:

List<object> x = new List<string>();

即使类型string继承自object