C#动态通用列表
我想创建一个通用的List ,其类型在运行时声明。
我可以做到以下几点,但由于它是动态的,我怀疑存在速度惩罚。 我正在为异国情调的数据库编写一个包装器,因此速度至关重要。
List gdb = new List()
我在动态generics类型中阅读了这篇文章 ,但无法让它发挥作用。 具体来说,该对象不会显示为List,因此没有添加方法。
Type ac; switch (trail[dataPos].Type) { case GlobalsSubscriptTypes.Int32: ac = typeof(System.Int32); break; case GlobalsSubscriptTypes.Int64: ac = typeof(System.Int64); break; default: ac = typeof(System.String); break; } var genericListType = typeof(List); var specificListType = genericListType.MakeGenericType(ac); var gdb = Activator.CreateInstance(specificListType);
如何让gdb显示为以下之一:
List List List
一旦使用了Activator.CreateInstance
,就可以将结果转换为适当的类型。 您可以使用IList
例如:
var gdb = (IList)Activator.CreateInstance(specificListType); gdb.Add(1);
请注意,如果您要添加的类型与generics类型不匹配,则上面会抛出ArgumentException
。
哦, gdb
是正确的类型。 由于您在运行时确定类型,因此编译器不知道它。 因此,它是静态类型为object
,并不显示Add
方法。 您有几个选项可以解决这个问题:
-
将其转换为正确的类型:
switch (trail[dataPos].Type) { case GlobalsSubscriptTypes.Int32: ((List
) gdb).Add(...); break; ... default: ((List ) gdb).Add(...); break; } -
转换为常见的超类型:
((System.Collections.IList) gdb).Add(...);
-
使用动态调用:
dynamic gdb = Activator.CreateInstance(specificListType); gdb.Add(...);
在您的情况下, gdb
将始终是System.Object
,因为CreateInstance
返回任何类型的对象。
这里有几个选项 – 您可以将其转换为IList
(非generics),因为您知道List
实现此接口,并使用IList.Add
。
或者,您可以将其声明为dynamic
,并使用动态绑定:
dynamic gdb = Activator.CreateInstance(specificListType);
这将使您编写代码,就好像它是相应类型的List
,并且调用将在运行时通过动态绑定进行绑定。
List
编译与List
完全相同的类型,对类型化List
没有速度惩罚,例如,超过装箱值类型。 但是如果你要向IList施放你仍然会有拳击惩罚FYI。
你可能遇到麻烦的是调用Activator
(一种reflection方法),因为直接调用构造函数可能会慢得多。
这有什么关系吗? 除非您实际运行配置文件,否则您将无法知道,因为它始终取决于您的实际使用情况。
我最好的客人,你真正想做的是:
IList gdb; switch (trail[dataPos].Type) { case GlobalsSubscriptTypes.Int32: gdb = new List(); break; case GlobalsSubscriptTypes.Int64: gdb = new List(); break; default: gdb = new List(); break; }
此外,如果你真的需要在没有拳击的情况下进行操作,可以使用通用帮助方法来完成所有工作:
switch (trail[dataPos].Type) { case GlobalsSubscriptTypes.Int32: return Helper(trail[dataPos]); case GlobalsSubscriptTypes.Int64: return Helper(trail[dataPos]); default: return Helper(trail[dataPos]); }