在 C# 中将引用转换为泛型 类

Convert references to generic classes in C#

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

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<Sub> 的引用分配给 Generic<Super> 的变量不会有问题,即使没有显式类型转换也是如此。

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

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

您已经进入了泛型方差的奇妙世界。泛型 类 总是类型不变的;换句话说 C<T1> 不能转换为 C<T2> 除非 T1T2 是完全相同的类型。

接口可以分别用 inout 声明为逆变和协变。这允许分别转换 "upwards" 和 "downwards",但 类 不能。

请参阅 以获得对方差的很好解释以及为什么 List 不变。

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

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

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

然后将通用 Class 更改为:

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);
}