在c#中将引用转换为泛型类
本文关键字:转换 泛型类 引用 | 更新日期: 2023-09-27 18:04:55
我首先在更复杂的上下文中尝试了通用类转换,结果发现这是不可能的。为了演示,我写了这个例子,它是我能想到的问题的最一般的表述,省略了任何不必要的东西:
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",所以我认为每个"Sub的泛型"都是"Super的泛型"。因此,我期望将对Generic<Sub>
的引用赋值给Generic<Super>
的变量是没有问题的,即使没有显式的类型转换。
但是。net框架告诉我这个转换是被禁止的,为什么?
那么,我为什么要这样做呢?假设我想构建一个只接受"任何泛型"的集合,我该如何规避转换呢?
如下所述: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);
}
你已经跌入了一个奇妙的通用变异世界。泛型类总是类型不变的;换句话说,除非T1
和T2
是完全相同的类型,否则C<T1>
不能转换为C<T2>
。
接口可以分别与in
和out
声明为逆变和协变。这允许分别"向上"answers"向下"强制转换,但类不能。
参见https://stackoverflow.com/a/2720046/7122,可以很好地解释方差和为什么List
是不变的。