如何从List<Parent>中获取子类型调用泛型方法DoSomethingElse
解决方法:用反射或动态类型获取运行时实际子类型
这个问题我之前也碰到过!核心原因是泛型类型参数是编译时确定的——你在foreach(Parent P in L)里调用DoSomething(P)时,编译器会直接把TypeP推断为Parent,哪怕运行时P是Child1或Child2,泛型参数也不会改变。要把实际的子类型传递给DoSomethingElse,得借助运行时的类型信息,这里有两种实用方案:
方案1:反射调用泛型方法
通过反射拿到DoSomethingElse的泛型方法定义,再用P的实际类型构造出具体的泛型方法并调用:
class Parent { } class Child1 : Parent { } class Child2 : Parent { } class Process { public Process() { List<Parent> L = new List<Parent>(); L.Add(new Child1()); L.Add(new Child2()); foreach(Parent P in L) { DoSomething(P); } } public void DoSomething(Parent P) { // 获取DoSomethingElse的泛型方法定义,再用实际类型构造 var targetMethod = typeof(Process).GetMethod(nameof(DoSomethingElse)) .MakeGenericMethod(P.GetType()); // 调用构造好的泛型方法 targetMethod.Invoke(this, null); } public void DoSomethingElse<T>() { T R = Activator.CreateInstance<T>(); // 现在R就是实际子类型的实例了,比如Child1或Child2 Console.WriteLine($"Created instance of: {typeof(T).Name}"); } }
方案2:用dynamic简化调用
dynamic会把类型解析推迟到运行时,这样调用泛型方法时会自动使用P的实际类型,写法更简洁:
class Parent { } class Child1 : Parent { } class Child2 : Parent { } class Process { public Process() { List<Parent> L = new List<Parent>(); L.Add(new Child1()); L.Add(new Child2()); foreach(Parent P in L) { // 把P转成dynamic,让运行时解析实际类型 DoSomething((dynamic)P); } } public void DoSomething<T>(T P) { DoSomethingElse<T>(); } public void DoSomethingElse<T>() { T R = Activator.CreateInstance<T>(); Console.WriteLine($"Created instance of: {typeof(T).Name}"); } }
这里的关键是把P转换成dynamic再传入DoSomething,这样编译器就不会在编译时把T固定为Parent,而是在运行时根据P的实际类型确定T。
为什么你原来的尝试无效?
你试过的TypeP = P.GetType()和DoSomethingElse<P.GetType()>()都没法工作,原因很简单:
P.GetType()返回的是一个Type对象,而TypeP是泛型类型参数,不能直接赋值;- 泛型方法的类型参数必须是编译时就能确定的类型,
P.GetType()是运行时才会拿到的信息,没法直接作为泛型参数使用。
这两种方案都能适配“子类数量不定,没法用switch判断”的场景,你可以根据需求选:反射灵活性更高但性能略差,dynamic写法更简洁但会失去编译时的类型检查。
内容的提问来源于stack exchange,提问作者xareth
相关产品推荐
相关产品推荐

