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我很高兴我能帮助你:)