【发布时间】:2008-11-21 05:47:38
【问题描述】:
是否可以在设计时不知道类型的情况下声明泛型的实例?
例子:
Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();
i 的类型可以是任何东西,而不是必须做:
List<int> list = new List<int();
【问题讨论】:
是否可以在设计时不知道类型的情况下声明泛型的实例?
例子:
Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();
i 的类型可以是任何东西,而不是必须做:
List<int> list = new List<int();
【问题讨论】:
如果您在编译时不知道类型,但您想要实际类型(即不是 List<object>)并且您不在具有适当的泛型方法/类型类型参数,那么你必须使用反射。
为了使反射更简单,我有时会在自己的代码中引入一个新的泛型类型或方法,因此我可以通过反射调用它,但之后只需使用普通泛型即可。例如:
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<T> BuildListHelper<T>(T item)
{
List<T> list = new List<T>();
list.Add(item);
return list;
}
当然,如果你不知道类型,你以后不能对列表做很多事情......这就是为什么这种事情经常失败的原因。但并非总是如此 - 我曾多次使用上述类似的东西,但类型系统并不能让我静态地表达我需要的所有内容。
编辑:请注意,尽管我在上面的代码中调用 Type.GetMethod,但如果您要执行很多次,您可能只想调用一次 - 毕竟,该方法不会改变。您可以将其设为静态(在上述情况下可以),并且您可能也希望将其设为私有。为了简化示例代码中的 GetMethod 调用,我将其保留为公共实例方法 - 否则您需要指定适当的绑定标志。
【讨论】:
我认为你能做的最好的事情是这样的:
static void Main(string[] args)
{
int i = 1;
var thelist = CreateList(i);
}
public static List<T> CreateList<T>(T t)
{
return new List<T>();
}
【讨论】:
如果您在设计时不知道类型,我会说您有一个 OBJECTS 列表(所有其他类型的基类)。
List<object> list = new List<object>();
【讨论】:
您也可以使用 Activator.CreateInstance。示例代码sn-p:
public class BaseRepository<T> where T : DataContext
{
protected T _dc;
public BaseRepository(string connectionString)
{
_dc = (T) Activator.CreateInstance(typeof(T), connectionString);
}
public void SubmitChanges()
{
_dc.SubmitChanges();
}
}
【讨论】:
如果您仍想键入 .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 );
}
【讨论】: