Операторы тестирования типов и выражения приведения — is, astypeof и приведения

Эти операторы и выражения выполняют проверку или преобразование типов. Операторis проверяет, совместим ли тип времени выполнения выражения с заданным типом. Операторas явно преобразует выражение в заданный тип, если его тип времени выполнения совместим с этим типом. Выражения приведения выполняют явное преобразование в целевой тип. Оператор typeof получаетSystem.Type экземпляр для типа.

Оператор is

Оператор is проверяет, совместим ли тип среды выполнения результата определенного выражения с указанным типом. Оператор is также проверяет результат выражения на соответствие шаблону.

Выражение с оператором проверки типа is имеет следующий вид:

E is T

где E представляет выражение, возвращающее значение, а T содержит имя или параметр типа. E не может использоваться как анонимный метод или лямбда-выражение.

Оператор is возвращает true, если результат выражения имеет значение, отличное от NULL, и выполняется любое из следующих условий.

Оператор is не учитывает заданные пользователем преобразования.

В следующем примере показано, что оператор is возвращает true, если тип результата выражения в среде выполнения является производным от указанного типа, то есть между этими типами существует преобразование ссылки:

public class Base { }

public class Derived : Base { }

public static class IsOperatorExample
{
    public static void Main()
    {
        object b = new Base();
        Console.WriteLine(b is Base);  // output: True
        Console.WriteLine(b is Derived);  // output: False

        object d = new Derived();
        Console.WriteLine(d is Base);  // output: True
        Console.WriteLine(d is Derived); // output: True
    }
}

В следующем примере показано, что оператор is учитывает упаковку-преобразование и распаковку-преобразование, но не учитывает числовые преобразования:

int i = 27;
Console.WriteLine(i is System.IFormattable);  // output: True

object iBoxed = i;
Console.WriteLine(iBoxed is int);  // output: True
Console.WriteLine(iBoxed is long);  // output: False

Дополнительные сведения о преобразованиях в C# см. в главе о преобразованиях в спецификации по языку C#.

Тестирование типов с сопоставлением шаблонов

Оператор is также проверяет результат выражения на соответствие шаблону. В следующем примере показано, как использовать шаблон объявления для проверки типа выражения в среде выполнения:

int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
    Console.WriteLine(a + b);  // output 30
}

Дополнительные сведения о поддерживаемых шаблонах см. в разделе Шаблоны.

Оператор as

Оператор as явным образом преобразует результат выражения в указанный ссылочный или поддерживающий значения NULL тип. Если такое преобразование невозможно, оператор as возвращает значение null. В отличие от выражения приведения, оператор as никогда не создает исключение.

Выражение имеет такой формат:

E as T

где E представляет выражение, возвращающее значение, а T содержит имя или параметр типа. Результат такого выражения аналогичен результату этого:

E is T ? (T)(E) : (T)null

за исключением того, что E вычисляется только один раз.

Оператор as рассматривает только преобразование ссылки, допускающие значение NULL преобразования, упаковку-преобразование и распаковку-преобразование. Оператор as нельзя использовать для определенного пользователем преобразования. Для этого используйте выражение приведения.

В следующем примере иллюстрируется использование оператора as.

IEnumerable<int> numbers = new[] { 10, 20, 30 };
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
    Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]);  // output: 40
}

Примечание

Как показано в примере выше, нужно сравнить результат выражения as со значением null, чтобы проверить, успешно ли выполнено преобразование. Оператор is можно использовать как для проверки успешности преобразования, так и для назначения результата новой переменной.

Выражение приведения

Выражение приведения в формате (T)E выполняет явное преобразование значения выражения E в тип T. Если явного преобразования из типа E в тип T не существует, возникает ошибка времени компиляции. Во время выполнения явное преобразование может завершиться сбоем, и выражение приведения может вызвать исключение.

Приведенный ниже пример демонстрирует явное числовое преобразование и преобразование ссылки:

double x = 1234.7;
int a = (int)x;
Console.WriteLine(a);   // output: 1234

IEnumerable<int> numbers = new int[] { 10, 20, 30 };
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count);  // output: 3
Console.WriteLine(list[1]);  // output: 20

Сведения о поддерживаемых явных преобразованиях см. в разделе о явных преобразованиях в спецификации по языку C#. Сведения о том, как определять пользовательские операторы явного или неявного преобразования, см. в разделе Операторы пользовательского преобразования.

Другие данные об использовании ()

Используйте скобки, чтобы вызвать метод или делегат.

Кроме того, с помощью круглых скобок можно настраивать порядок выполнения операций в выражении. Дополнительные сведения см. в разделе Операторы C#.

typeof - оператор

Оператор typeof получает экземпляр System.Type для указанного типа. Оператор typeof принимает в качестве аргумента имя типа или параметр типа, как показано в следующем примере:

void PrintType<T>() => Console.WriteLine(typeof(T));

Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]

Аргумент не должны должен быть типом, требующим заметок к метаданным. Далее приведены примеры типов.

  • dynamic
  • string? (или любой ссылочный тип, допускающий значение NULL)

Эти типы не представлены непосредственно в метаданных. Типы включают в себя атрибуты, описывающие базовый тип. В обоих случаях можно использовать базовый тип. Вместо dynamic можно использовать object. Вместо string? можно использовать string.

Кроме того, оператор typeof можно использовать с несвязанными универсальными типами. В имени несвязанного универсального типа должно содержаться правильное количество запятых, то есть на одну меньше, чем число параметров этого типа. В следующем примере показано использование оператора typeof с несвязанным универсальным типом:

Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]

Оператор typeof не может принимать выражение в качестве аргумента. Чтобы получить экземпляр System.Type для типа среды выполнения результата выражения, используйте метод Object.GetType.

Тестирование типов с оператором typeof

Используйте оператор typeof, чтобы проверить совместимость типа среды выполнения результата выражения с указанным типом. В следующем примере показано различие между проверкой типов, выполненной с помощью оператора typeof и оператора is:

public class Animal { }

public class Giraffe : Animal { }

public static class TypeOfExample
{
    public static void Main()
    {
        object b = new Giraffe();
        Console.WriteLine(b is Animal);  // output: True
        Console.WriteLine(b.GetType() == typeof(Animal));  // output: False

        Console.WriteLine(b is Giraffe);  // output: True
        Console.WriteLine(b.GetType() == typeof(Giraffe));  // output: True
    }
}

Возможность перегрузки оператора

Операторы is, asи typeof нельзя перегружать.

Определяемый пользователем тип нельзя использовать для перегрузки оператора (), но на его основе можно определить пользовательские преобразования типа и выполнить их с помощью выражения приведения. Дополнительные сведения см. в разделе Операторы пользовательского преобразования.

Спецификация языка C#

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:

См. также