C# 动态声明泛型类型实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/307984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Declare a generic type instance dynamically
提问by benPearce
Is it possible to declare an instance of a generic without knowing the type at design-time?
是否可以在设计时不知道类型的情况下声明泛型的实例?
Example:
例子:
Int i = 1;
List<typeof(i)> list = new List<typeof(i)>();
where the type of i could be anything, instead of having to do:
i 的类型可以是任何类型,而不必执行以下操作:
List<int> list = new List<int();
采纳答案by Jon Skeet
If you don't know the type at compile-time, but you want the actual type (i.e. not List<object>
) andyou're not in a generic method/type with the appropriate type parameter, then you have to use reflection.
如果您在编译时不知道类型,但您想要实际类型(即 not List<object>
)并且您不在具有适当类型参数的泛型方法/类型中,那么您必须使用反射。
To make the reflection simpler, I've sometimes introduced a new generic type or method in my own code, so I can call that by reflection but then just use normal generics after that. For example:
为了使反射更简单,我有时会在自己的代码中引入新的泛型类型或方法,因此我可以通过反射调用它,但之后只使用普通泛型。例如:
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;
}
Of course, you can't do an awful lot with the list afterwards if you don't know the type... that's why this kind of thing often falls down. Not always though - I've used something like the above on a few occasions, where the type system just doesn't quite let me express everything I need to statically.
当然,如果你不知道类型,你之后就无法对列表做很多事情......这就是为什么这种事情经常失败。但并非总是如此 - 我曾在几次使用类似上述内容的情况下,类型系统并不能让我静态地表达我需要的一切。
EDIT: Note that although I'm calling Type.GetMethod in the code above, if you were going to execute it a lot you'd probably want to just call it once - after all, the method isn't going to change. You may be able to make it static (you could in the case above) and you probably want to make it private too. I left it as a public instance method for the simplicity of the GetMethod call in sample code - you'd need to specify the appropriate binding flags otherwise.
编辑:请注意,虽然我在上面的代码中调用了 Type.GetMethod,但如果您要执行很多次,您可能只想调用一次 - 毕竟,该方法不会改变。您可以将其设为静态(在上述情况下您可以),并且您可能也希望将其设为私有。为了简化示例代码中的 GetMethod 调用,我将其保留为公共实例方法 - 否则您需要指定适当的绑定标志。
回答by Nathan
I think the best you are going to be able to do is something like this:
我认为你能做的最好的事情是这样的:
static void Main(string[] args)
{
int i = 1;
var thelist = CreateList(i);
}
public static List<T> CreateList<T>(T t)
{
return new List<T>();
}
回答by seanb
Pretty sure you can do that, they don't have to be fixed at compile time like templates in c++.
非常确定您可以做到这一点,它们不必像 C++ 中的模板那样在编译时修复。
An example that is similar here: http://geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx
这里有一个类似的例子:http: //geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx
回答by abelenky
If you don't know the type at design-time, I'd say you have a list of OBJECTS (the base class for all other types).
如果您在设计时不知道类型,我会说您有一个 OBJECTS 列表(所有其他类型的基类)。
List<object> list = new List<object>();
回答by KevinT
You can also use Activator.CreateInstance. Example code snippet:
您还可以使用 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();
}
}
回答by Brian B.
See the answer from the similar question "Dynamically Create a Generic Type for Template". The only difference is that they are generating the type from the command line, the rest you should be able to adapt to your needs.
请参阅类似问题“Dynamically Create a Generic Type for Template”中的答案。唯一的区别是它们是从命令行生成类型的,其余的您应该能够适应您的需求。
As an aside, you cannot call typeof on an instance - to get the type of an instance (for example "i" call GetType():
顺便说一句,您不能在实例上调用 typeof - 以获取实例的类型(例如“i”调用 GetType():
Type intType = i.GetType();
回答by baretta
If you still want to type .Add(), .Remove(), do foreach etc. you can treat the List as a regular "old" System.Collections.IList, since this interface is luckily implemented by List<T>.
如果您仍想键入 .Add()、.Remove()、foreach 等,您可以将 List 视为常规的“旧”System.Collections.IList,因为该接口幸运地由 List<T> 实现。
And since all other posted answers to this question shows pretty much every other possible way to create an instance of a List<T> dynamically, i will show one last way to do it. I personally use this method when creating generic instances, when i don't really know nothing about the type at compile time, and the type must be passed as a string, perhaps coming from the application configuration file. In this example, T is System.String for simplicity but it could be anything:
由于该问题的所有其他已发布答案几乎显示了动态创建 List<T> 实例的所有其他可能方法,因此我将展示最后一种方法。我个人在创建泛型实例时使用这种方法,当我在编译时对类型一无所知时,类型必须作为字符串传递,可能来自应用程序配置文件。在这个例子中,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 );
}