C# 中的类型检查:typeof、GetType 还是 is?如何不在这三者中迷失
\n\n每个 C# 开发者迟早都会遇到需要检查对象类型的情况。看起来很简单,对吧?但当面前有三个选项——typeof、GetType() 和 is——时,你会眼花缭乱,脑海中自然浮现一个问题:“到底该选哪一个?”
这篇文章不仅仅是文档的枯燥摘录。我们将通过实际示例分析每种方法,揭示其中的陷阱,并给出明确的建议。阅读之后,你将不再犹豫,并确切知道在特定情况下该使用哪种工具。开始吧!
\n\n为什么要在 C# 中检查类型?
\n\n在深入细节之前,让我们先回顾一下为什么需要这样做。C# 是一种强类型语言,但这并不排除对象的类型仅在运行时才已知的情况。以下是最常见的场景:
\n\n- \n
- 处理接口和基类:你将对象作为
object或基类型接收,但需要了解其真实的“本质”。 \n - 序列化和反序列化:JSON 或 XML 以字符串形式传入,需要恢复为具体的类型。 \n
- 反射(Reflection):当你仅知道类型名称,需要动态创建对象或调用方法时。 \n
- 日志记录和调试:有时只需在日志中输出当前正在处理的类型。 \n
这时,我们的三位主角登场了。让我们逐一深入了解它们。
\n\ntypeof —— 静态地展望未来
\n\ntypeof 是一个运算符,它返回编译时已知类型的 System.Type 对象。它就像一个信息服务:“告诉我类的名称,我就给你关于它的所有信息。”
工作原理:
\nType stringType = typeof(string);\nConsole.WriteLine(stringType.FullName); // 输出:System.String\n\nType intType = typeof(int);\nConsole.WriteLine(intType.FullName); // 输出:System.Int32\n\n关键特性:typeof 不需要对象的实例。这是一个静态操作。你对编译器说:“我有一个类型 MyClass,请给我它的元数据。”
何时使用:
\n- \n
- 当你需要根据类名(而非对象)获取类型时。 \n
- 在特性(Attribute)中(例如
[AttributeUsage(typeof(MyAttribute))])。 \n - 在泛型中:
typeof(List<>)。 \n
陷阱:typeof 始终返回你在代码中指定的确切类型。它不了解继承关系。如果你有 class Dog : Animal { },那么 typeof(Animal) 永远不会变成 typeof(Dog)。
GetType() —— 动态调查
\n\n与 typeof 不同,GetType() 方法是在对象的实例上调用的。它获取内存中的实际对象,并告诉你:“啊哈,原来你实际上是这个!”
示例:
\nobject obj = "你好,世界!";\nType typeOfObj = obj.GetType();\nConsole.WriteLine(typeOfObj.FullName); // 输出:System.String\n\n// 现在来个技巧:\nobject obj2 = 42;\nType typeOfObj2 = obj2.GetType();\nConsole.WriteLine(typeOfObj2.FullName); // 输出:System.Int32\n\n请注意:变量 obj 被声明为 object,但 GetType() 能够“看穿”这个包装,并返回 System.String。这就是动态类型确定。
何时使用:
\n- \n
- 当你需要在运行时了解对象的确切类型时。 \n
- 用于类型比较:
obj.GetType() == typeof(MyClass)。 \n