96

Why this works

if (mycontrol.GetType() == typeof(TextBox))
{} 

and this do not?

Type tp = typeof(mycontrol);

But this works

Type tp = mycontrol.GetType();

I myself use is operator for checking type but my understanding fails when I use typeof() and GetType()

Where and when to use GetType() or typeof()?

Jarrod Dixon
  • 15,727
  • 9
  • 60
  • 72
Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208

4 Answers4

142

typeof is an operator to obtain a type known at compile-time (or at least a generic type parameter). The operand of typeof is always the name of a type or type parameter - never an expression with a value (e.g. a variable). See the C# language specification for more details.

GetType() is a method you call on individual objects, to get the execution-time type of the object.

Note that unless you only want exactly instances of TextBox (rather than instances of subclasses) you'd usually use:

if (myControl is TextBox)
{
    // Whatever
}

Or

TextBox tb = myControl as TextBox;
if (tb != null)
{
    // Use tb
}
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 9
    Your Line `'The operand of typeof is always the name of a type or type parameter - never an expression with a value (e.g. a variable)'` is the perfect answer to my question. Thanks for helping me out. – Nikhil Agrawal Jul 03 '12 at 13:47
71

typeof is applied to a name of a type or generic type parameter known at compile time (given as identifier, not as string). GetType is called on an object at runtime. In both cases the result is an object of the type System.Type containing meta-information on a type.

Example where compile-time and run-time types are equal:

string s = "hello";

Type t1 = typeof(string);
Type t2 = s.GetType();

t1 == t2 ==> true

Example where compile-time and run-time types are different:

object obj = "hello";

Type t1 = typeof(object); // ==> object
Type t2 = obj.GetType();  // ==> string!

t1 == t2 ==> false

i.e., the compile time type (static type) of the variable obj is not the same as the runtime type of the object referenced by obj.


Testing types

If, however, you only want to know whether mycontrol is a TextBox then you can simply test

if (mycontrol is TextBox)

Note that this is not completely equivalent to

if (mycontrol.GetType() == typeof(TextBox))    

because mycontrol could have a type that is derived from TextBox. In that case the first comparison yields true and the second false! The first and easier variant is OK in most cases, since a control derived from TextBox inherits everything that TextBox has, probably adds more to it and is therefore assignment compatible to TextBox.

public class MySpecializedTextBox : TextBox
{
}

MySpecializedTextBox specialized = new MySpecializedTextBox();
if (specialized is TextBox)       ==> true

if (specialized.GetType() == typeof(TextBox))        ==> false

Casting

If you have the following test followed by a cast and T is nullable ...

if (obj is T) {
    T x = (T)obj; // The casting tests, whether obj is T again!
    ...
}

... you can change it to ...

T x = obj as T;
if (x != null) {
    ...
}

Testing whether a value is of a given type and casting (which involves this same test again) can both be time consuming for long inheritance chains. Using the as operator followed by a test for null is more performing.

Starting with C# 7.0 you can simplify the code by using pattern matching:

if (obj is T t) {
    // t is a variable of type T having a non-null value.
    ...
}

Btw.: this works for value types as well. Very handy for testing and unboxing. Note that you cannot test for nullable value types:

if (o is int? ni) ===> does NOT compile!

This is because either the value is null or it is an int. The following code works for int? o as well as for object o = new Nullable<int>(x);:

if (o is int i) ===> OK!

I like it, because it eliminates the need to access the Nullable<T>.Value property.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • The static type of `o` can be either `int?` or `object`. If e.g., `42` was assigned to `o`, then `o is int i` returns `true` and `i` is `42`. If `null` was assigned to `o` it returns `false` and `i` undefined. – Olivier Jacot-Descombes Nov 03 '22 at 11:12
  • Oh, because this tests the value, not the type as being declared. If an `int?` is assigned an integer, then the value is an `int`. If it is assigned `null` then the type is undefined. `null` does not have a type. But you can test `o.GetType() == typeof(int?)` to test for `int?`. Note that `Nullable` has special compiler support as mentioned in the [reference source](https://referencesource.microsoft.com/#mscorlib/system/nullable.cs): *"[..] we have special type system support that says a boxed Nullable can be used where a boxed is used [..]"* – Olivier Jacot-Descombes Nov 03 '22 at 11:38
9

typeOf is a C# keyword that is used when you have the name of the class. It is calculated at compile time and thus cannot be used on an instance, which is created at runtime. GetType is a method of the object class that can be used on an instance.

Fr33dan
  • 4,227
  • 3
  • 35
  • 62
5

You may find it easier to use the is keyword:

if (mycontrol is TextBox)
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328