结论:用 typeof 获取编译时已知类型名,gettype() 获取运行时实际类型,type.gettype() 仅用于字符串查类型;typeof 不接受变量,否则编译失败;gettype() 返回真实创建类型,注意 null 和性能问题。

直接说结论:想拿编译时已知的类型名,用 typeof;想看运行时变量实际是什么类型(尤其涉及多态或不确定来源的对象),必须用 GetType();而 Type.GetType() 是靠字符串查类型,不是“获取变量类型”的正路,别混用。
为什么不能对变量写 typeof(myVar)
typeof 不是函数,是编译器关键字,只认“类型字面量”——比如 int、List<string></string>、MyClass。它在编译阶段就要能静态确定类型,所以传变量名会直接报错 CS0277:“'myVar' 不是有效的类型”。
常见错误现象:
-
var x = "hello"; typeof(x)→ 编译失败 -
object obj = new Dog(); typeof(obj)→ 编译失败,哪怕obj实际是Dog
正确做法:如果真要基于变量推类型,只能走 GetType()。
GetType() 为什么常返回“意外”的类型?
因为它是运行时行为,返回的是对象“真实创建的类型”,不是声明类型。这对多态很关键,但也容易让人困惑。
使用场景举例:
-
Animal a = new Dog(); a.GetType()返回Dog,不是Animal -
int i = 42; ((object)i).GetType()返回Int32(注意装箱后仍是值类型) -
string s = null; s.GetType()→ 立刻抛NullReferenceException
性能影响:每次调用都有轻微开销,高频循环里应缓存结果,比如 var t = obj.GetType(); 后复用 t。
typeof 和 GetType() 的返回值能直接比较吗?
能,但得小心——它们返回的都是 Type 对象,相等性比较是按类型标识判断的,不是字符串名。
关键差异点:
-
typeof(string) == "abc".GetType()→true(同一个Type实例) -
typeof(object) == new Dog().GetType()→false,哪怕Dog继承自object - 泛型擦除不适用:
typeof(List<int>) != typeof(List<string>)</string></int>,二者是完全不同的Type
容易踩的坑:用 .Name 或 .FullName 字符串比较来判断类型是否一致,会漏掉泛型参数、命名空间差异、嵌套类等细节,应该直接比 Type 引用或用 IsAssignableFrom 等语义方法。
别把 Type.GetType("xxx") 当作变量类型获取手段
Type.GetType(string) 是纯字符串查找,和变量本身无关。它需要完整命名空间(如 "System.String"),且类型必须已加载进当前 Assembly,查不到就返回 null ——不是抛异常,所以不判空后续调 GetMethods() 就崩。
典型误用:
-
Type.GetType(myVar.GetType().FullName)→ 多此一举,还可能因 Assembly 上下文不同返回null -
Type.GetType("MyClass")→ 缺少命名空间,99% 返回null
真正适合它的场景只有两个:插件系统动态加载类型、配置文件驱动的类型注册。日常变量类型分析,请坚定用 GetType()。
最常被忽略的点:GetType() 对 null 零容忍,而 typeof 根本不接触实例。只要涉及用户输入、反序列化结果、DI 容器解析出的对象,先做非空检查再调 GetType(),否则上线后随机崩。











