Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何声明具有不同类型和未知类型的泛型列表,以及如何使用仅在运行时已知的类型初始化泛型?_C#_List_Generics_Types - Fatal编程技术网

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;
}