类型 X 不能用作泛型类型 Y 中的类型参数 T
The type X cannot be used as type parameter T in the generic type Y
我看不出以下代码有什么问题,也看不出如何修复它。 (也许我误解了泛型。)
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
}
编译器抱怨它不能在通用类型 Y<T>
中使用 X<I>
作为类型参数 T
。
这是一个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; }
}
请注意我添加到类型 Y
的定义中的附加通用参数 I
和约束。
您对 Y
的初始定义过于严格。 C# 区分 ISomeInterface
和任何实现 ISomeInterface
的类型。
为什么会这样?
.NET 编译器有一种处理泛型类型的特殊方法。对于每个泛型类型,编译器将基于泛型类型参数创建一个单独的类型,而不是在运行时使用。例如 List<int>
和 List<string>
将是完全不同的类型,都表现出由 List<_>
通用类型定义的行为,但具有实际类型 int
或 string
烘焙成编译器生成的具体类型。
当您定义 class Y<T> where T : X<ISomeInterface>
时,您 "seal" 将 X
的通用参数设为 ISomeInterface
。编译器将接受任何继承 X<ISomeInterface>
但不继承 X<SomethingElse>
的类型,即使 SomethingElse
本身是 ISomeInterface
的实现。这是因为片段 where T : X<ISomeInterface>
导致 ISomeInterface
在 Y<T>
的类型定义中成为 "baked in"。这种行为是预期的,并且是将泛型编译为实际代码的方式的副作用。出于同样的原因,不能执行以下操作:
List<object> x = new List<string>();
即使类型 string
继承自 object
。
我看不出以下代码有什么问题,也看不出如何修复它。 (也许我误解了泛型。)
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
}
编译器抱怨它不能在通用类型 Y<T>
中使用 X<I>
作为类型参数 T
。
这是一个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; }
}
请注意我添加到类型 Y
的定义中的附加通用参数 I
和约束。
您对 Y
的初始定义过于严格。 C# 区分 ISomeInterface
和任何实现 ISomeInterface
的类型。
为什么会这样?
.NET 编译器有一种处理泛型类型的特殊方法。对于每个泛型类型,编译器将基于泛型类型参数创建一个单独的类型,而不是在运行时使用。例如 List<int>
和 List<string>
将是完全不同的类型,都表现出由 List<_>
通用类型定义的行为,但具有实际类型 int
或 string
烘焙成编译器生成的具体类型。
当您定义 class Y<T> where T : X<ISomeInterface>
时,您 "seal" 将 X
的通用参数设为 ISomeInterface
。编译器将接受任何继承 X<ISomeInterface>
但不继承 X<SomethingElse>
的类型,即使 SomethingElse
本身是 ISomeInterface
的实现。这是因为片段 where T : X<ISomeInterface>
导致 ISomeInterface
在 Y<T>
的类型定义中成为 "baked in"。这种行为是预期的,并且是将泛型编译为实际代码的方式的副作用。出于同样的原因,不能执行以下操作:
List<object> x = new List<string>();
即使类型 string
继承自 object
。