代码之家  ›  专栏  ›  技术社区  ›  benPearce

动态声明泛型类型实例[重复]

  •  29
  • benPearce  · 技术社区  · 17 年前

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

    例子:

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

    List<int> list = new List<int();
    
    7 回复  |  直到 17 年前
        1
  •  46
  •   Jon Skeet    17 年前

    如果您在编译时不知道类型,但需要实际类型(即不知道 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调用,我将其保留为公共实例方法,否则需要指定适当的绑定标志。

        2
  •  1
  •   Nathan    17 年前

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

    static void Main(string[] args)
    {
        int i = 1;
        var thelist = CreateList(i);
    }
    
    public static List<T> CreateList<T>(T t)
    {
        return new List<T>();
    }
    
        3
  •  1
  •   abelenky    17 年前

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

    List<object> list = new List<object>();
    
        4
  •  1
  •   KevinT    17 年前

    您还可以使用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();
       }
    }
    
        5
  •  0
  •   baretta    17 年前

    如果仍要键入.Add()、.Remove()、do foreach等。可以将列表视为常规的“旧”System.Collections.IList, 由于此接口是由列表实现的<T>。

    而且,由于对这个问题的所有其他发布的答案几乎都显示了创建列表实例的所有其他可能方法<T>动态地, 我将展示最后一种方法。 我个人在创建泛型实例时使用这种方法,当我在编译时对类型一无所知时, 类型必须作为字符串传递,可能来自应用程序配置文件。

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