Type Checking in C#: typeof, GetType or is? How Not to Get Lost in Three Pines
\n\nEvery C# developer, sooner or later, faces the need to check an object's type. It seems simple enough, right? But when you have three options — typeof, GetType(), and is — your eyes dart around, and a logical question arises in your head: "Which one should I choose?".
This article is not just a dry excerpt from the documentation. We will break down each approach with real-world examples, uncover pitfalls, and give clear recommendations. After reading, you will stop guessing and will know exactly which tool to use in a specific situation. Let's go!
\n\nWhy Check Types in C# at All?
\n\nBefore diving into the details, let's remember why we need this. C# is a strongly typed language, but that doesn't eliminate situations where an object's type is only known at runtime. Here are the most common scenarios:
\n\n- \n
- Working with interfaces and base classes: You receive an object as
objector a base type, and you need to know its true "nature". \n - Serialization and deserialization: JSON or XML arrives as a string, and you need to restore a specific type. \n
- Reflection: When you dynamically create objects or call methods, knowing only the type name. \n
- Logging and debugging: Sometimes you just need to log what type you are currently working with. \n
And this is where our three heroes enter the stage. Let's get to know each one up close.
\n\ntypeof — A Static Look into the Future
\n\ntypeof is an operator that returns a System.Type object for a type known at compile time. It works like a reference service: "Tell me the class name, and I'll give you all the information about it."
How it works:
\nType stringType = typeof(string);\nConsole.WriteLine(stringType.FullName); // Output: System.String\n\nType intType = typeof(int);\nConsole.WriteLine(intType.FullName); // Output: System.Int32\n\nKey feature: typeof does not require an object instance. It is a static operation. You tell the compiler: "I have the type MyClass, give me its metadata."
When to use:
\n- \n
- When you need the type by class name, not by an object. \n
- In attributes (e.g.,
[AttributeUsage(typeof(MyAttribute))]). \n - In generics:
typeof(List<>). \n
Pitfall: typeof always returns the exact type you specified in the code. It knows nothing about inheritance. If you have class Dog : Animal { }, then typeof(Animal) will never become typeof(Dog).
GetType() — Dynamic Investigation
\n\nUnlike typeof, the GetType() method is called on an instance of an object. It takes the actual object stored in memory and says: "Aha, so this is who you really are!".
Example:
\nobject obj = "Hello, world!";\nType typeOfObj = obj.GetType();\nConsole.WriteLine(typeOfObj.FullName); // Output: System.String\n\n// And now a trick:\nobject obj2 = 42;\nType typeOfObj2 = obj2.GetType();\nConsole.WriteLine(typeOfObj2.FullName); // Output: System.Int32\n\nNotice: the variable obj is declared as object, but GetType() "sees through" this wrapper and returns System.String. This is dynamic type determination.
When to use:
\n- \n
- When you need to know the exact type of an object at runtime. \n
- For type comparison:
obj.GetType() == typeof(MyClass). \n