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

C# 在C语言中将引用转换为泛型类#,c#,generics,collections,type-conversion,C#,Generics,Collections,Type Conversion,我首先尝试在更复杂的上下文中进行泛型类转换,结果发现这是不可能的。因此,为了演示的目的,我写了这个样本,这是我能想到的关于我的问题的最一般的公式,省略了任何不必要的东西: using System; using System.Collections.Generic; namespace testapp { class Program { static void Main(string[] args) { // proble

我首先尝试在更复杂的上下文中进行泛型类转换,结果发现这是不可能的。因此,为了演示的目的,我写了这个样本,这是我能想到的关于我的问题的最一般的公式,省略了任何不必要的东西:

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 { }
}
使用系统;
使用System.Collections.Generic;
命名空间testapp
{
班级计划
{
静态void Main(字符串[]参数)
{
//问题
Generic subvar=新的Generic();
一般超变量;

supervar=(Generic)subvar;//您已经跌入了Generic variance的奇妙世界。Generic类总是类型不变的;换句话说,
C
不能转换为
C
,除非
T1
T2
是完全相同的类型

接口可以分别与
in
out
声明为逆变和协变。这允许分别强制转换“向上”和“向下”,但类不能


请参阅,以获得方差的非常好的解释以及为什么
List
是不变的。

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

接口可以分别与
in
out
声明为逆变和协变。这允许分别强制转换“向上”和“向下”,但类不能

有关方差的非常好的解释以及为什么
List
是不变的,请参见。

如本文所述:您可以使用out-Generic修饰符来实现您的目标

为此,您必须添加如下所示的新接口:

interface IGeneric<out T> where T: Super{}
接口IGeneric,其中T:Super{}
然后将泛型类更改为:

class Generic<T> : IGeneric<T> where T : Super
class-Generic:IGeneric其中T:Super
然后你会是:

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);
}
static void Main(字符串[]args)
{
IGeneric subvar=新的泛型();
IGeneric超变种;
supervar=subvar;//不需要强制转换
列表=新列表();
列表添加(超级变量);
}
如本文所述:您可以使用out-Generic修饰符来实现您的目标

为此,您必须添加如下所示的新接口:

interface IGeneric<out T> where T: Super{}
接口IGeneric,其中T:Super{}
然后将泛型类更改为:

class Generic<T> : IGeneric<T> where T : Super
class-Generic:IGeneric其中T:Super
然后你会是:

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);
}
static void Main(字符串[]args)
{
IGeneric subvar=新的泛型();
IGeneric超变种;
supervar=subvar;//不需要强制转换
列表=新列表();
列表添加(超级变量);
}

仅仅因为
Sub
Super
的子类型并不意味着
Generic
Generic
的子类型。仅仅因为
Sub
Super
的子类型并不意味着
Generic
Generic
的子类型。感谢您对协变和逆变的快速提示接口。我会将它们添加到我的项目中。如果我能实现我试图用它们做的事情,我会将此标记为答案。感谢对协变和逆变接口的快速提示。我会将它们添加到我的项目中。如果我能实现我试图用它们做的事情,我会将此标记为答案。谢谢你的回答。现在我唯一的答案是剩下的问题是我还没有决定,哪个答案值得绿色检查:)。我将把它交给这个答案,因为它可能是对偶然发现这个问题的用户最有帮助的答案。但我强烈建议阅读另一个答案,以便理解为什么这个界面是必要的。@wulf21,如果它有帮助,我同意帽子这是一个更好的选择为“接受”回答并投了赞成票:)@wulf21我很高兴能帮助你:)谢谢你的回答。现在我唯一的问题是我还没有决定,哪个答案值得绿色检查:)。我将把它给这个,因为它可能是对随机发现这个问题的用户最有帮助的一个。但我强烈建议阅读另一个回答,以便理解为什么界面是必要的。@wulf21,如果有帮助的话,我同意这是一个更好的选择,对于“已接受”的答案,我已经投了赞成票:)@wulf21我很高兴我能帮助你:)