【问题标题】:Convert references to generic classes in C#在 C# 中转换对泛型类的引用
【发布时间】:2015-10-17 09:12:15
【问题描述】:

我首先在更复杂的上下文中尝试了泛型类转换,结果发现这是不可能的。因此,仅出于演示目的,我编写了这个示例,它是关于我能想到的问题的最一般表述,省略了任何不必要的内容:

using System;
using System.Collections.Generic;

namespace testapp
{
    class Program
    {
        static void Main(string[] args)
        {
            // problem
            Generic<Sub> subvar = new Generic<Sub>();
            Generic<Super> supervar;
            supervar = (Generic<Super>)subvar; // <--fails
            // reason for asking
            List<Generic<Super>> list = new List<Generic<Super>>();
            list.Add(supervar);
        }
    }

    class Super { }

    class Sub:Super { }

    class Generic<T> where T : Super { }
}

所以总的来说:因为每个“Sub”都是“Super”,我认为每个“Generic of Sub”都是“Generic of Super”。所以我希望将Generic&lt;Sub&gt; 的引用分配给Generic&lt;Super&gt; 的变量不会有问题,即使没有显式类型转换。

但是 .NET Framework 告诉我这种转换是被禁止的,为什么?

那么,我为什么要这样做?假设我想构建一个只接受“anything 的泛型”的集合,我将如何绕过转换?

【问题讨论】:

  • 仅仅因为SubSuper 的子类型 暗示Generic&lt;Sub&gt;Generic&lt;Super&gt; 的子类型。

标签: c# generics collections type-conversion


【解决方案1】:

您偶然发现了泛型变异的奇妙世界。泛型类总是类型不变的;换句话说,C&lt;T1&gt; 不能转换为 C&lt;T2&gt;,除非 T1T2 是完全相同的类型。

接口可以分别用inout 声明为逆变和协变。这允许分别投射“向上”和“向下”,但类不能。

请参阅 https://stackoverflow.com/a/2720046/7122 以获得对方差的很好解释以及为什么 List 是不变的。

【讨论】:

  • 感谢协变和逆变接口的快速提示。我会将它们添加到我的项目中。如果我能实现我想要对他们做的事情,我会将其标记为答案。
【解决方案2】:

如此处所述:https://msdn.microsoft.com/en-us/library/dd469487.aspx 您可以使用 out 通用修饰符来实现您的目标。

为此,您必须添加一个如下所示的新界面:

interface IGeneric<out T> where T: Super{}

然后将您的通用类更改为:

class Generic<T> : IGeneric<T> where T : Super

然后你的 Main 将是:

static void Main(string[] args)
{
    IGeneric<Sub> subvar = new Generic<Sub>();
    IGeneric<Super> supervar;
    supervar = subvar; // No cast required
    List<IGeneric<Super>> list = new List<IGeneric<Super>>();
    ist.Add(supervar);
}

【讨论】:

  • 感谢您的回答。现在我唯一剩下的问题是我还没有决定,哪个答案值得绿色检查:)。我会把它交给这个,因为对于随机偶然发现这个问题的用户来说,它可能是最有帮助的。但我强烈建议您也阅读其他答案,以了解为什么界面是必要的。
  • @wulf21,如果有帮助,我同意这是“已接受”答案的更好选择,并已投赞成票:)
  • @wulf21 很高兴能帮到你:)
猜你喜欢
  • 2022-08-27
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多