C# 如何声明具有不同类型和未知类型的泛型列表,以及如何使用仅在运行时已知的类型初始化泛型?
这是一个由两部分组成的问题 首先C# 如何声明具有不同类型和未知类型的泛型列表,以及如何使用仅在运行时已知的类型初始化泛型?,c#,list,generics,types,C#,List,Generics,Types,这是一个由两部分组成的问题 首先 我有一个名为ComponentList的类,如下所示: public class ComponentList<T> : List<T> where T : Component { } public类ComponentList:List其中T:Component { } 现在我想创建一个无类型组件列表的空列表: List<ComponentList<>> MasterList = new List<Com
我有一个名为ComponentList的类,如下所示:
public class ComponentList<T> : List<T> where T : Component
{
}
public类ComponentList:List其中T:Component
{
}
现在我想创建一个无类型组件列表的空列表:
List<ComponentList<>> MasterList = new List<ComponentList<>>();
List MasterList=newlist();
我得到一个错误,因为ComponentList需要指定一个泛型类型,即使我还没有尝试初始化任何ComponentList(只是包含它们的主列表)。在不初始化任何组件列表的情况下,我如何声明组件列表的主列表(因为我计划在运行时使用仅在运行时已知的类型初始化它们)?毕竟,主列表需要包含不同泛型类型的组件列表,而不仅仅是一个
其次我知道以前有人问过这个问题,但我似乎无法理解任何建议解决方案的概念 正如您所知,我有一个名为MasterList的
列表,它是一个组件列表列表(一个自定义类)。ComponentList是一个未定义类型的泛型类(被约束为组件的子类型)
在下面的示例中,我试图检查ComponentList泛型类型(从MasterList引用)是否与此类(从中调用代码的类)相同
if(主列表[i].GetType()==typeof(组件列表))
{
}
问题是,代码是从未知的子类自动调用的,而不是从父类调用的。因此,ComponentList泛型类型需要与子类的类型进行比较,而不是与这个基类进行比较。因此,“this.GetType”取代了实际基类的硬编码名称
组件列表中传递的this.GetType()
类型返回一个“预期类型”错误,这显然是因为GetType()
返回编译时类型,而不是运行时类型(这正是我需要的)
那么我怎样才能得到运行时类型呢?如果我做不到,除了完成我想做的事情,什么是最好的选择?(我听说过一种叫做“反思”的东西,可能对我有所帮助,但我真的不明白)。我认为你的要求是不可能的,但也许这正是你需要的
public class ComponentA : Component { }
public class ComponentB : Component { }
public class Component { }
public class ComponentList<T> : List<T> where T : Component
{
}
class Program
{
static void Main(string[] args)
{
ComponentList<Component> MasterList = new ComponentList<Component>();
MasterList.Add(new ComponentA());
MasterList.Add(new ComponentB());
for (int i = 0; i < MasterList.Count; i++)
{
if (MasterList[i] is ComponentA)
{
}
}
}
}
公共类组件a:Component{}
公共类组件B:组件{}
公共类组件{}
公共类ComponentList:列表,其中T:组件
{
}
班级计划
{
静态void Main(字符串[]参数)
{
ComponentList主列表=新ComponentList();
添加(新组件a());
添加(新组件b());
for(int i=0;i
您无法在运行时确定泛型类型。C#(实际上是所有的.Net)就是这样设计的。编译器对待泛型类型的方式与显式定义的类型几乎相同
考虑以下几点:
class MyGenericClass<T>
{
public static T MyProperty { get; set; }
}
class MyIntClass
{
public static int MyProperty { get; set; }
}
class UseThem
{
public void test()
{
// both are JIT'ed to be exactly the same machine code
var foo = MyGenericClass<int>.MyProperty;
var bar = MyOtherClass.MyProperty;
}
}
class MyGenericClass
{
公共静态myt属性{get;set;}
}
类MyIntClass
{
公共静态int MyProperty{get;set;}
}
班级使用他们
{
公开无效测试()
{
//两者都被JIT处理为完全相同的机器代码
var foo=MyGenericClass.MyProperty;
var bar=MyOtherClass.MyProperty;
}
}
因此,必须为泛型类提供一个类型,以便JIT知道要编译什么
可能的替代方案
如果所有可能最终成为泛型类型的可能类型都是相似的(继承自相同的基类或实现类似的接口),则可以使用接口或基类作为泛型类型实例化泛型类:
List<ComponentList<ComponentBase>> MasterList = new List<ComponentList<ComponentBase>>();
// -OR-
List<ComponentList<IMyComponent>> MasterList = new List<ComponentList<IMyComponent>>();
List MasterList=newlist();
//-或-
列表主列表=新列表();
我有一种预感,您应该能够通过一些创造性的重构来定义一个公共接口或基类 我在尝试为一个用C#编写的游戏设置实体组件系统时也遇到了这个问题。实际上没有一种方法可以将组件存储为它们的实际类型,您必须将它们全部存储为Component
s并强制转换它们
我将其设置为字典
,作为组件管理器
类的私有成员。添加组件的方法是泛型的,并检查其类型是否包含在字典中,因此获取IEnumerable
非常简单:
public IEnumerable<T> EnumerateComponents<T>()
where T : Component
{
foreach (Component c in components[typeof(T)])
yield return (T)c;
}
public IEnumerable枚举组件()
其中T:组件
{
foreach(组件[typeof(T)]中的组件c)
收益率(T)c;
}
(您还需要检查字典是否包含typeof(T)
,该位与从字典继承的自定义我的集合内置,以避免在类似情况下出现异常。)
只要字典从未在泛型方法之外修改(并且绝对不能从外部直接访问),类型安全性是“有保证的”。不理想,但速度足够快,永远不会成为你的瓶颈
编辑
需要探索的可能是C#4的dynamic
关键字。我没有详细研究过,但是将组件存储为列表可能会更好(或者可能会引入太多的开销),需要考虑的是。使用泛型的全部目的是编译时类型安全。类型在编译时已知,需要提供参数。那么,我如何制作一个非泛型(因此不是编译时类型安全)的列表?如此广泛的概括消除了将T限制在有用的东西上的目的。您还可以初始化一个列表
,然后丢失所有强输入。设置如何
public IEnumerable<T> EnumerateComponents<T>()
where T : Component
{
foreach (Component c in components[typeof(T)])
yield return (T)c;
}