更新 2:我发布的第一个示例仍然没有 100% 回答问题,因为它涉及到 List<int> 的强制转换,这是在编译时已知的类型。下面是一个仅反射的解决方案,说明您如何可以使用对类型参数本身一无所知的泛型类型。但是,正如你所看到的,它......好吧,恶心;)
Type userType = GetUserSuppliedType();
// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });
// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);
// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");
// We better hope this matches userType!
object input = GetUserSuppliedInput();
// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
throw new InvalidOperationException("That isn't going to work!");
}
// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });
更新:好的,如果您坚持这样做,这里有一个例子说明它是如何可能的——但非常麻烦!
Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });
object listObject = Activator.CreateInstance(listOfInt32Type);
List<int> list = (List<int>)listObject;
list.Add(1);
泛型不能像这样工作,因为Type 对象可以是任何东西。考虑这段代码:
var list = new List<int>();
list.Add(1);
上面代码中list的类型已知为List<int>,它定义了list上哪些操作是合法的,比如Add(1)。
现在考虑一下:
Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);
当t 是Type 对象而不是编译器可以解析的类型(如int)的名称 时,实际上不可能使用它来实例化泛型类型类型——或者更确切地说,它是可能的(参见Andrey's answer),但你不能真正使用以任何通用方式生成的对象。
现在,您可能认为这样的事情应该可以工作:
Type t = typeof(int);
var list = new List<t>();
list.Add(1);
...但仅仅因为 t 的值在编译时(由您)知道并不会改变一般的工作方式。
无论如何,是的,可以使用反射;但如果你沿着这条路走下去,你就会致力于一个非常注重反思的解决方案。我的意思是,总的来说,这并不是一件特别现实的事情。