C#运行时无法直接获取泛型方法调用的实际类型实参,但可通过MethodInfo是否为封闭式泛型方法(IsGenericMethod=true且ContainsGenericParameters=false)并调用GetGenericArguments()获取;或通过参数实例的GetType()推测;或借助Expression/委托捕获类型信息。

运行时无法直接获取泛型方法调用中传入的**实际类型实参**(比如 T 具体是 string 还是 int),因为 C# 的泛型在 JIT 编译后会为每个封闭类型生成独立的本地代码,而方法签名本身不保留调用现场的类型信息。但你可以通过几种间接方式“推断”或“重建”出它——关键看你的上下文和目标。
看 MethodInfo 是否来自已构造的方法调用
如果你手头的 MethodInfo 是从某个具体泛型方法实例(如 list.Where<string>(...)</string>)反射获得的,那它已经是**封闭式泛型方法**:
- 调用
methodInfo.IsGenericMethod == true且methodInfo.ContainsGenericParameters == false - 再调用
methodInfo.GetGenericArguments(),就能拿到Type[]数组,例如{ typeof(string) } - 这适用于:你通过委托、表达式树、或
typeof(MyClass).GetMethod("Foo").MakeGenericMethod(typeof(string))明确构造过方法的情况
从调用栈或参数对象反向推测
若你只拿到一个泛型方法的开放定义(如 MethodInfo 对应 Foo<t>(T value)</t>),而没有调用上下文,就无法知道 T 是什么——除非你有传入的参数实例:
- 检查第一个参数(或关键参数)的
obj.GetType(),它大概率就是T的实际类型 - 例如:调用
Foo(42),参数是int,那T很可能就是int - 注意:这不严谨(比如
T可能是基类或接口),但对多数业务场景足够实用
借助 Expression 或委托捕获类型信息
如果控制调用方,可改用表达式树或泛型委托来“携带”类型信息:
- 把泛型方法包装成
Expression<func tresult>></func>,编译后可通过Body和Parameters提取泛型参数 - 或定义委托
Action<t> handler = x => { ... };</t>,然后用handler.Method.GetGenericArguments()拿到T - 这种方式把类型信息固化在委托实例里,比纯反射更可靠
注意 Java 的区别(避免混淆)
Java 的泛型存在类型擦除,运行时连泛型定义都不可见;而 .NET 的泛型在元数据中完整保留了定义和构造信息。所以你在 .NET 中能拿到 GetGenericArguments(),但前提是这个 MethodInfo 本身是封闭构造过的——不是所有泛型方法反射结果都能直接给出实际类型。

















