typeof是C#编译时运算符,只能接类型名(如typeof(string)),不可接变量或表达式;需获取运行时类型应使用obj.GetType();它在DI注册、特性检查等场景中不可替代。

typeof 不是函数,不能传变量,也不能在运行时动态决定类型 —— 它只认编译期就写死的类型名。
typeof 后面只能跟类型名,不能跟变量或表达式
常见错误是写成 typeof(obj) 或 typeof(someVariable),这会直接编译失败,报错 CS0246: The type or namespace name 'xxx' could not be found。
-
typeof(int)、typeof(List<string>)、typeof(MyClass)都合法 -
typeof(x)(x 是变量)、typeof(123)、typeof(someObject.GetType())全部非法 - 想查变量的实际类型,该用
someObject.GetType(),不是typeof
泛型类型写法必须严格匹配:List<> vs List<string>
泛型定义和具体泛型是两个不同 Type,typeof(List<>) 和 typeof(List<string>) 返回的对象不相等,IsAssignableFrom 也不直接成立。
-
typeof(List<>)表示“未绑定的泛型类型”,用于反射中判断是否为某泛型构造器 -
typeof(List<string>)是具体闭合类型,能创建实例、注册 DI 服务 - 检查一个对象是否为
List<T>实例?得用obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(List<>)
typeof 常见误用:拿它替代 nameof 或硬编码字符串
比如写 typeof(MyService).Name 获取类名,看似可行,但实际触发了反射,性能差且无法被编译器验证 —— 类名改了,这里不会报错。
- 要获取类型名称作日志或键名,优先用
nameof(MyService) -
typeof(MyService).FullName虽然能拿到完整命名空间,但同样有反射开销;若只是做 DI 注册,直接传typeof(MyService)即可,无需转字符串 - 别在属性名、配置项里混用
typeof(T).Name,容易因大小写或嵌套类名(如UserQuery+Model)出错
typeof 在 DI 和反射中真正不可替代的场景
只有 typeof 能在不创建实例的前提下,把类型作为一等公民传递 —— 这是它存在的根本价值。
- ASP.NET Core 手动注册服务:
services.AddSingleton<IMyService, MyService>()底层依赖typeof(IMyService)和typeof(MyService) - 检查特性:
typeof(MyController).IsDefined(typeof(AllowAnonymousAttribute), false),没实例也能查 - 泛型约束辅助:
public void RegisterHandler<T>() where T : class => services.AddTransient<IHandler<T>, Handler<T>>();,内部仍靠typeof构造类型参数
最易被忽略的一点:所有基于 typeof 的反射操作,一旦涉及 GetMethods()、GetProperties() 等调用,就已脱离编译期安全 —— 此时名字拼错、访问级别不对、泛型参数不匹配,全要到运行时才暴露。


















