Операторы тестирования типов и выражения приведения — is
as
и typeof
приведение
Эти операторы и выражения выполняют проверку типов или преобразование типов. Оператор is
проверяет, совместим ли тип времени выполнения выражения с заданным типом. Оператор as
явно преобразует выражение в заданный тип, если его тип времени выполнения совместим с этим типом. Выражения приведения выполняют явное преобразование в целевой тип. Оператор typeof
получает System.Type экземпляр для типа.
Оператор is
Оператор is
проверяет, совместим ли тип среды выполнения результата определенного выражения с указанным типом. Оператор is
также проверяет результат выражения на основе шаблона.
Выражение с оператором проверки типа is
имеет следующий вид:
E is T
где E
представляет выражение, возвращающее значение, а T
содержит имя или параметр типа. E
не может использоваться как анонимный метод или лямбда-выражение.
Оператор is
возвращает true
, если результат выражения имеет значение, отличное от NULL, и выполняется любое из следующих условий.
Тип результата выражения в среде выполнения —
T
.Тип результата выражения в среде выполнения является производным от типа
T
, реализует интерфейсT
или существует другое неявное преобразование ссылок из него вT
.Тип результата выражения в среде выполнения является типом, допускающим значение NULL, имеющим базовый тип
T
, а Nullable<T>.HasValue —true
.Существует упаковка-преобразование или распаковка-преобразование из типа результата выражения в среде выполнения в тип
T
.
Оператор 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
и as
typeof
операторы не могут быть перегружены.
Определяемый пользователем тип нельзя использовать для перегрузки оператора ()
, но на его основе можно определить пользовательские преобразования типа и выполнить их с помощью выражения приведения. Дополнительные сведения см. в разделе Операторы пользовательского преобразования.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#: