Поделиться через


Операторы тестирования типов и выражения приведения — isasи typeof приведение

Эти операторы и выражения выполняют проверку типов или преобразование типов. Оператор 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 List<int>(){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

int[] ints = [10, 20, 30];
IEnumerable<int> numbers = ints;
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и astypeof операторы не могут быть перегружены.

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

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

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

См. также