动态声明generics类型实例
是否可以在设计时不知道类型的情况下声明generics的实例?
例:
Int i = 1; List list = new List();
我的类型可以是任何东西,而不是必须做:
List list = new List<int();
如果您在编译时不知道类型,但是您想要实际类型(即不是List
) 并且您没有使用相应类型参数的generics方法/类型,那么您必须使用reflection。
为了使reflection更简单,我有时在我自己的代码中引入了一个新的generics类型或方法,所以我可以通过reflection调用它,但之后只需使用普通generics。 例如:
object x = GetObjectFromSomewhere(); // I want to create a List> containing the existing // object, but strongly typed to the "right" type depending // on the type of the value of x MethodInfo method = GetType().GetMethod("BuildListHelper"); method = method.MakeGenericMethod(new Type[] { x.GetType() }); object list = method.Invoke(this, new object[] { x }); // Later public IList BuildListHelper (T item) { List list = new List (); list.Add(item); return list; }
当然,如果你不知道这种类型,你就不能对列表做很多事情……这就是为什么这种事情常常会失败的原因。 并非总是如此 – 我曾经在某些场合使用了类似上面的东西,其中类型系统并不能让我静态地表达我需要的一切。
编辑:请注意,虽然我在上面的代码中调用Type.GetMethod,如果你要执行它很多,你可能只想调用一次 – 毕竟,该方法不会改变。 您可以将其设置为静态(您可以在上面的情况下)并且您可能也想将其设为私有。 我将它作为公共实例方法保留,以简化示例代码中的GetMethod调用 – 否则您需要指定适当的绑定标志。
我认为你能做的最好的事情是这样的:
static void Main(string[] args) { int i = 1; var thelist = CreateList(i); } public static List CreateList (T t) { return new List (); }
如果你在设计时不知道类型,我会说你有一个OBJECTS列表(所有其他类型的基类)。
List
您还可以使用Activator.CreateInstance。 示例代码段:
public class BaseRepository where T : DataContext { protected T _dc; public BaseRepository(string connectionString) { _dc = (T) Activator.CreateInstance(typeof(T), connectionString); } public void SubmitChanges() { _dc.SubmitChanges(); } }
非常确定你可以这样做,它们不必像编译c ++中的模板一样在编译时修复。
这里类似的一个例子: http : //geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx
请参阅类似问题“动态创建模板的通用类型”的答案。 唯一的区别是他们从命令行生成类型,其余的应该能够适应您的需求。
顺便说一句,你不能在实例上调用typeof – 获取实例的类型(例如“i”调用GetType():
Type intType = i.GetType();
如果您仍想键入.Add(),. Remove(),请执行foreach等操作,您可以将List视为常规的“旧”System.Collections.IList,因为此接口幸运地由List
由于此问题的所有其他发布的答案几乎都显示了动态创建List
Type T = typeof ( string ); // replace with actual T string typeName = string.Format ( "System.Collections.Generic.List`1[[{0}]], mscorlib", T.AssemblyQualifiedName ); IList list = Activator.CreateInstance ( Type.GetType ( typeName ) ) as IList; System.Diagnostics.Debug.Assert ( list != null ); // list.Add ( "string 1" ); // new T list.Add ( "string 2" ); // new T foreach ( object item in list ) { Console.WriteLine ( "item: {0}", item ); }