﻿# Type check in C\#: typeof, GetType, is

One of the basic and most common operations with types is their check at runtime\. In different cases — to get information about the type and to check the type — we should use different methods and operators\. Below is their brief overview\.

## The typeof operator

The _typeof_ operator returns the _System\.Type_ instance\. The instance corresponds to the type, the name of which is specified in the argument\.

```cpp
Type typeOfInt = typeof(int);
// [System.Int32]

Type typeOfString = typeof(string);
// [System.String]
```

Note that in the case of generic types, the _typeof_ operator can accept both arguments of a constructed and an unbound type\.

```cpp
var typeOfGenericList = typeof(List<>);
// [System.Collections.Generic.List`1[T]]

var typeOfListOfStrings = typeof(List<String>);
// [System.Collections.Generic.List`1[System.String]]
```

## The GetType method

_GetType_ is an instance method of the _Object_ class\. This method can obtain the actual type of an object at the application runtime\.

```cpp
Object obj = new Object();
Object str = String.Empty;

Type type1 = obj.GetType();
// [System.Object]

Type type2 = str.GetType();
// [System.String]
```

## The is operator

At runtime, the _is_ operator checks whether the expression type is compatible with the type specified in the operand\.

```cpp
Object obj = new Object();
Object str = String.Empty;

Console.WriteLine(obj is Object); // True
Console.WriteLine(obj is String); // False

Console.WriteLine(str is Object); // True
Console.WriteLine(str is String); // True
```

This example shows that the _is_ operator doesn't check the exact match\. Instead, the operator checks the compatibility, meaning that the actual object type is specified or derived from it\.

The _is_ operator also has a variety of other features\. They are listed below\.

**Check for null**

After we check the actual type, we also check the value for the _null_ inequation\.

```cpp
Object obj = null;
Console.WriteLine(obj is Object); // False, since obj is null
```

**The boxed type check**

We can check the boxed value actual type with the _is_ operator\.

```cpp
Object obj = 42; // boxing

Console.WriteLine(obj is int); // True
Console.WriteLine(obj is double); // False
```

**The Nullable<T\> underlying type check**

The _is_ operator allows you to check whether a value exists in the _Nullable<T\>_ instance \(_Nullable<T\>\.HasValue_\) and its type\.

```cpp
int? nullableInt1 = 62;
int? nullableInt2 = null;

Console.WriteLine(nullableInt1 is int?);   // True
Console.WriteLine(nullableInt1 is int);    // True
Console.WriteLine(nullableInt1 is double); // False

Console.WriteLine(nullableInt2 is int?);   // False
Console.WriteLine(nullableInt2 is int);    // False
Console.WriteLine(nullableInt2 is double); // False
```

## How to choose between typeof, GetType, is

To select an operator/method for working with types, you can use the following approach:

* use the _typeof_ operator to obtain the _System\.Type_ instance for the type name;
* if you need to check the exact type match, use the _System\.Type_ instance obtained via the _GetType_ method;
* if the compatibility check is sufficient, use the _is_ operator\.

The example below clearly demonstrates the difference between type checking via the _GetType_ method and via the _is_ operator\.

```cpp
class A     { .... }        
class B : A { .... }
class C : B { .... }

void Foo()
{
  A obj = new C();

  Console.WriteLine(obj.GetType() == typeof(B)); // False
  Console.WriteLine(obj is B);                   // True
}
```

The actual type of the object referenced by _obj_ is _C\._ Therefore, the _GetType_ method for _obj_ returns an instance of _System\.Type_ corresponding to _C\._ The result of the _typeof\(B\)_ operator is an instance describing type _B\._ Comparing objects describing different types, as expected, results in _false_\.

The _is_ operator checks for compatibility, not exact match\. Since the compatibility of an object of type _C_ with _B_ is checked, the result will be _true_\.