C# 动态声明泛型类型实例

C# 动态声明泛型类型实例,c#,.net,generics,C#,.net,Generics,在设计时是否可以在不知道类型的情况下声明泛型的实例 例如: Int i = 1; List<typeof(i)> list = new List<typeof(i)>(); inti=1; 列表=新列表(); 我可以是任何类型的人,而不必做: List<int> list = new List<int(); List List=new List我想你能做的最好的事情就是这样: static void Main(string[] args) {

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

例如:

Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();
inti=1;
列表=新列表();
我可以是任何类型的人,而不必做:

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

List List=new List我想你能做的最好的事情就是这样:

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

public static List<T> CreateList<T>(T t)
{
    return new List<T>();
}
static void Main(字符串[]args)
{
int i=1;
var thelist=CreateList(i);
}
公共静态列表CreateList(T)
{
返回新列表();
}

<代码> > p>非常肯定你能做到,它们不必像C++中的模板那样在编译时被固定。
这里有一个类似的例子:

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

List List=新列表();

您也可以使用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();
   }
}
公共类BaseRepository,其中T:DataContext
{
受保护的T_dc;
公共基本存储库(字符串连接字符串)
{
_dc=(T)Activator.CreateInstance(typeof(T),connectionString);
}
公开作废提交更改()
{
_dc.提交更改();
}
}

查看类似问题的答案。唯一的区别是,它们是从命令行生成类型的,其余的您应该能够适应您的需要

另外,您不能对实例调用typeof来获取实例的类型(例如“i”调用GetType():


如果您在编译时不知道类型,但需要实际的类型(即非
列表
),并且不在具有适当类型参数的泛型方法/类型中,则必须使用反射

为了简化反射,我有时在自己的代码中引入了一个新的泛型类型或方法,因此我可以通过反射调用它,但之后只使用普通泛型。例如:

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;
}
object x=GetObjectFromSomewhere();
//我想创建一个包含现有
//对象,但强类型为“右”类型,具体取决于
//关于x值的类型
MethodInfo method=GetType().GetMethod(“BuildListHelper”);
method=method.MakeGenericMethod(新类型[]{x.GetType()});
object list=method.Invoke(这是一个新对象[]{x});
//后来
公共IList BuildListHelper(T项)
{
列表=新列表();
列表。添加(项目);
退货清单;
}
当然,如果你不知道列表的类型,那么你以后就不能对列表做太多的事情……这就是为什么这种事情经常失败的原因。虽然不总是这样——我已经在一些场合使用过类似上面的东西,其中类型系统不能让我静态地表达我需要的一切


编辑:请注意,尽管我在上面的代码中调用了Type.GetMethod,但如果您要经常执行它,您可能只想调用一次-毕竟,该方法不会更改。您可以将其设置为静态(在上面的情况下可以)您可能也想将其私有化。为了简化示例代码中的GetMethod调用,我将其保留为公共实例方法-否则您需要指定适当的绑定标志。

如果您仍然希望键入.Add()、.Remove()、do foreach等。您可以将该列表视为常规的“旧”System.Collections.IList, 因为这个接口是通过列表实现的

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

这依赖于编译器能够推断类型——这意味着它必须在编译时知道类型。不,您仍然可以创建一个适当类型的列表,并将其传递给某个可以对正确类型进行强制转换的对象,然后以静态类型的方式处理它。仅仅因为一段代码不知道类型这并不意味着什么都不知道类型。您可以返回一个非泛型的IList(列表支持),那么返回的列表就有用了。在这种情况下,首先使用ArrayList会更简单。啊,但是当它被转换为IList时,向集合中添加错误的类型仍然会遇到一个关于它是错误类型的异常,不是吗?是的,它会抛出一个异常。12年后,这个答案再次帮助了我!谢谢@JonSkeeT
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 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 );
}