﻿# Проверка типов в C\#: typeof, GetType, is

Одной из базовых и при том наиболее частых операций работы с типами является их проверка на этапе исполнения\. Как для получения информации о типе, так и для его проверки, в разных случаях следует использовать различные методы и операторы\. Ниже представлен их краткий обзор\.

## Оператор typeof

Оператор _typeof_ возвращает экземпляр _System\.Type_, соответствующий типу, имя которого указано в аргументе\.

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

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

Обратите внимание, что в случае с обобщёнными типами оператор _typeof_ может принимать как аргументы сконструированного, так и неограниченного типа\.

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

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

## Метод GetType

_GetType_ – экземплярный метод класса _Object_, который позволяет получить фактический тип объекта на этапе исполнения приложения\.

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

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

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

## Оператор is

Оператор _is_ позволяет на этапе исполнения проверить, совместим ли тип выражения с указанным в операнде типом\.

```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
```

Как видно из этого примера, оператор _is_ проверяет не точное соответствие, а совместимость – то есть то, что фактический тип объекта является указанным или производным от него\.

Оператор _is_ обладает и рядом других особенностей, перечисленных ниже\.

**Проверка на null**

Кроме проверки фактического типа, также производится проверка значения на неравенство _null_\.

```cpp
Object obj = null;
Console.WriteLine(obj is Object); // False, так как obj - null
```

**Проверка упакованного типа**

С помощью оператора _is_ можно проверить фактический тип упакованного значения\.

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

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

**Проверка нижележащего типа Nullable<T\>**

Оператор _is_ позволяет проверять, наличие значения в экземпляре _Nullable<T\>_ \(_Nullable<T\>\.HasValue_\) и его тип\.

```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
```

## Выбор между typeof, GetType, is

Для выбора оператора / метода работы с типами можно использовать следующий подход:

* для получения экземпляра _System\.Type_ по имени типа используйте оператор _typeof_;
* если необходима проверка точного соответствие типа, используйте для проверки экземпляр _System\.Type_, полученный через метод _GetType_;
* если достаточно проверки совместимости, используйте оператор _is_\.

Более наглядно разница между проверкой типа через метод _GetType_ и оператор _is_ демонстрируется в примере ниже\.

```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
}
```

Фактический тип объекта, на который ссылается _obj,_ – _C_\. Следовательно, метод _GetType_ для _obj_ возвращает экземпляр _System\.Type_, соответствующий _C_\. Результат работы оператора _typeof\(B\)_ \- экземпляр, описывающий тип _B_\. Сравнение объектов, описывающих разные типы, ожидаемо даёт _false_\.

Оператор _is_ проверяет совместимость, а не точное соответствие\. Так как проверяется совместимость объекта типа _C_ с _B_, результатом будет _true_\.