动态声明泛型类型实例

时间:2008-11-21 05:47:39

标签: c# .net generics

是否可以在设计时不知道类型的情况下声明泛型的实例?

示例:

Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();

其中i的类型可以是任何东西,而不是必须:

List<int> list = new List<int();

7 个答案:

答案 0 :(得分:46)

如果您在编译时不知道类型,但是您想要实际类型(即不是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调用 - 否则您需要指定适当的绑定标志。

答案 1 :(得分:1)

我认为你能做的最好的事情就是这样:

static void Main(string[] args)
{
    int i = 1;
    var thelist = CreateList(i);
}

public static List<T> CreateList<T>(T t)
{
    return new List<T>();
}

答案 2 :(得分:1)

如果你在设计时不知道类型,我会说你有一个OBJECTS列表(所有其他类型的基类)。

List<object> list = new List<object>();

答案 3 :(得分:1)

您还可以使用Activator.CreateInstance。示例代码段:

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

答案 4 :(得分:0)

非常确定你能做到这一点,它们不必像编译模板一样在编译时修复。

此处类似的示例:http://geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx

答案 5 :(得分:0)

查看类似问题"Dynamically Create a Generic Type for Template"的答案。唯一的区别是他们从命令行生成类型,其余的你应该能够适应你的需求。

顺便说一下,你不能在实例上调用typeof - 获取实例的类型(例如“i”调用GetType():

Type intType = i.GetType();

答案 6 :(得分:0)

如果您仍想输入.Add(),. Remove(),请执行foreach等操作,您可以将List视为常规的“旧”System.Collections.IList, 因为这个界面幸运地由List&lt; T&gt;实现。

由于此问题的所有其他发布的答案几乎都显示了创建List&lt; T&gt;的实例的所有其他可能方式。动态, 我将展示最后一种方法。 我个人在创建泛型实例时使用此方法,当我在编译时对类型一无所知时, 并且类型必须作为字符串传递,可能来自应用程序配置文件。 在这个例子中,为简单起见,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 );
}