我想创建一个通用List<>其类型在运行时声明。
我可以做到以下几点,但由于它是动态的,我怀疑存在速度惩罚。我正在为异国情调的数据库编写一个包装器,因此速度至关重要。
List<dynamic> gdb = new List<dynamic>()
我在动态泛型类型中阅读this post,但无法使其工作。具体来说,该对象不会显示为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<System.Int32>
List<System.Int64>
List<System.String>
答案 0 :(得分:5)
使用Activator.CreateInstance
后,您可以将结果转换为适当的类型。您可以使用IList
例如:
var gdb = (IList)Activator.CreateInstance(specificListType);
gdb.Add(1);
请注意,如果您添加的类型与通用类型不匹配,则上述内容会引发ArgumentException
。
答案 1 :(得分:3)
哦,gdb
是正确类型的。由于您确定运行时的类型,编译器不知道它。因此,它被静态输入为object
,并且不显示Add
方法。您有几个选项可以解决这个问题:
将其转换为正确的类型:
switch (trail[dataPos].Type)
{
case GlobalsSubscriptTypes.Int32:
((List<int>) gdb).Add(...);
break;
...
default:
((List<String>) gdb).Add(...);
break;
}
转换为常见的超类型:
((System.Collections.IList) gdb).Add(...);
使用动态调用:
dynamic gdb = Activator.CreateInstance(specificListType);
gdb.Add(...);
答案 2 :(得分:1)
在您的情况下,gdb
始终为System.Object
,因为CreateInstance
会返回任何类型的对象。
这里有几个选项 - 您可以将其转换为IList
(非通用),因为您知道List<T>
实现了此接口,并使用IList.Add
。
或者,您可以将其声明为dynamic
,并使用动态绑定:
dynamic gdb = Activator.CreateInstance(specificListType);
这将允许您编写代码,就好像它是适当类型的List<T>
一样,并且调用将在运行时通过动态绑定进行绑定。
答案 3 :(得分:1)
List<dynamic>
编译与List<object>
完全相同的类型,对类型List<int>
没有速度惩罚,例如,超过拳击值类型。但是如果你要向IList施放你仍然会有拳击惩罚FYI。
调用Activator
(一种反射方法)可能会遇到麻烦,因为直接调用构造函数可能会慢得多。
这有什么关系吗?除非您实际运行配置文件,否则您将无法知道,因为它始终取决于您的实际使用情况。
我最好的客人,你真正想做的是:
IList gdb;
switch (trail[dataPos].Type)
{
case GlobalsSubscriptTypes.Int32:
gdb = new List<int>();
break;
case GlobalsSubscriptTypes.Int64:
gdb = new List<long>();
break;
default:
gdb = new List<string>();
break;
}
此外,如果你真的需要在没有拳击的情况下进行操作,那么可以使用通用的辅助方法来完成所有工作:
switch (trail[dataPos].Type)
{
case GlobalsSubscriptTypes.Int32:
return Helper<int>(trail[dataPos]);
case GlobalsSubscriptTypes.Int64:
return Helper<long>(trail[dataPos]);
default:
return Helper<string>(trail[dataPos]);
}