我没有看到以下代码有什么问题,或者我如何解决它。 (也许我误解了泛型类型。)
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
作为类型参数Y<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; }
}
注意我添加到类型I
的定义中的附加通用参数Y
和约束。
您对Y
的初始定义过于严格。 C#在ISomeInterface
和任何实现ISomeInterface
的类型之间有所不同。
为什么会这样?
.NET编译器有一种处理泛型类型的特殊方法。对于每种泛型类型,编译器将基于泛型类型参数创建单独的类型,而不是在运行时使用。例如,List<int>
和List<string>
将是完全不同的类型,所有类型都展示了由List<_>
泛型类型定义的行为,但实际类型为int
或string
,这些类型被编译器生成的具体类型。
当你定义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
。