【问题标题】:The type X cannot be used as type parameter T in the generic type Y类型 X 不能用作泛型类型 Y 中的类型参数 T
【发布时间】:2019-01-20 18:47:05
【问题描述】:

我看不出以下代码有什么问题,或者我可以如何修复它。 (也许我误解了泛型。)

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&lt;T&gt; 中使用X&lt;I&gt; 作为类型参数T

【问题讨论】:

  • 调用/使用此代码的代码在哪里?
  • @ZoharPeled 我的错误,请检查更新的代码示例。

标签: c# .net generics interface covariance


【解决方案1】:

这是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&lt;int&gt;List&lt;string&gt; 将是完全不同的类型,它们都表现出List&lt;_&gt; 泛型类型定义的行为,但实际类型intstring 被烘焙到编译器生成的具体类型中。

当您定义class Y&lt;T&gt; where T : X&lt;ISomeInterface&gt; 时,您将X 的通用参数“密封”为ISomeInterface。编译器将接受任何继承 X&lt;ISomeInterface&gt; 但不接受 X&lt;SomethingElse&gt; 的类型,即使 SomethingElse 本身是 ISomeInterface 的实现。这是因为片段where T : X&lt;ISomeInterface&gt; 导致ISomeInterface 被“嵌入”到Y&lt;T&gt; 的类型定义中。这种行为是预期的,并且是泛型如何编译为实际代码的副作用。出于同样的原因,不能执行以下操作:

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

即使string 类型继承自object

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    相关资源
    最近更新 更多