动态声明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 list = new 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 实例的所有其他可能方式,因此我将展示最后一种方法。 我个人在创建generics实例时使用此方法,当我在编译时对类型一无所知时,类型必须作为字符串传递,可能来自应用程序配置文件。 在这个例子中,为简单起见,T是System.String,但它可以是任何东西:

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