具有 c# 中列表的动态类型
本文关键字:动态 类型 列表 具有 | 更新日期: 2023-09-27 18:35:24
我有一个小问题要问你们。
我想这样做:
Type[] classes = new Type[]{ Class1, Class2 };
foreach(Type t in classes){
List<t> list = new List<t>();
}
有没有办法做到这一点?
不能在运行时强制转换为泛型类型,因为泛型中的类型需要在编译时解析。
可以使用反射以动态方式创建泛型类型,但除非对强制转换进行硬编码,否则得到的只是一个对象。
我真的不知道你想要什么,我必须同意一个评论,这是一个 XY 问题。我倾向于冒昧地声明,即在某个地方存在试图解决的设计问题,而不是直接解决设计问题,或者询问您直接尝试实现的目标的问题。
您可以使用以下代码创建类型,然后可以使用dynamic
类型来隐藏List<T>
的各种成员,而无需知道/关心它是一个列表或T
是什么:
using System;
using System.Collections.Generic;
namespace ConsoleApplication61
{
class Program
{
static void Main(string[] args)
{
dynamic o = CreateGeneric(typeof(List<>), typeof(int));
o.Add(1);
Console.WriteLine(o[0]);
Console.Read();
}
public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
return Activator.CreateInstance(specificType, args);
}
}
}
上面的示例鸭子键入Add
方法和索引器。DLR 在运行时执行类型处理和鸭子类型化 - 例如,知道1
是一个int
。
澄清一下,我可能不会在生产中使用这样的代码(除非你的要求非常具体),并且任何类型不匹配的问题都会在运行时发生;所以你要么需要非常准确地键入(有限的智能感知),要么有良好的错误处理。
感谢这篇博文的CreateGeneric
方法。
这假定 .NET 4 具有新的 CLR。正如@MartinLiversage还指出的那样,此特定示例假定您正在以某种强类型方式使用该列表。在我的示例中,我将int
传递给隐藏在dynamic
中的List<int>
。
自从 .NET 4 发布以来,我们几乎一直在使用它。我们有一个具有更大代码库的大型应用程序。 dynamic
在应用程序中不会使用一次,在测试代码库中只会使用几次。这并不是说"不要使用它",而是说"大多数时候,你不需要它"。
这样做:
foreach(Type t in classes)
{
var listType = typeof(List<>).MakeGenericType(t);
var instance = Activator.CreateInstance(listType);
}
这可以通过 Type.MakeGenericType 方法实现
这是我发现的一个应该适合你的漂亮方法:CodeRef
public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
return Activator.CreateInstance(specificType, args);
}
并像这样使用它:
var o = CreateGeneric(typeof(List<>), t);
不幸的是,要添加项目,您必须这样做(其中项目是您要添加的项目)。
MethodInfo addMethod = o.GetType().GetMethod("Add");
addMethod.Invoke(o, new object[] { item.ToType(t) });
或者使用另一个答案中提到的Generic
类型。
你可以试试这个:
Type[] classes = new Type[] { typeof(A), typeof(B) };
foreach (Type t in classes)
{
Type genericType = typeof(List<>).MakeGenericType(t);
var list = Activator.CreateInstance(genericType);
}
如果你想在一个列表中保留对象,那么它们可能有一些共同点。
在这种情况下,我认为,就像评论中提到的 L.B 一样,您在这里问了一个错误的问题。
可能是您遇到的设计问题。考虑这些类型,看看它们有什么共同点,并考虑从一个基本类型派生或使两者实现相同的接口。在这种情况下,您将能够实例化基类型/接口的对象列表并使用这些对象。
只是为了给你一个良好的开端:
abstract class Vehicle {
public int NumberOfWheels { get; set; }
}
class Car : Vehicle
{
public Car()
{
NumberOfWheels = 4;
}
}
class Bicycle : Vehicle
{
public Bicycle()
{
NumberOfWheels = 2;
}
}
static void Main(string[] args)
{
var v1 = new Car();
var v2 = new Bicycle();
var list = new List<Vehicle>();
list.Add(v1);
list.Add(v2);
foreach (var v in list)
{
Console.WriteLine(v.NumberOfWheels);
}
Console.ReadKey();
}