在 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>
除非 T1
和 T2
是完全相同的类型。
接口可以分别用 in
和 out
声明为逆变和协变。这允许分别转换 "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);
}
我首先在更复杂的上下文中尝试了通用 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>
除非 T1
和 T2
是完全相同的类型。
接口可以分别用 in
和 out
声明为逆变和协变。这允许分别转换 "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);
}