Operadores de teste de tipo e expressões de molde - is
, as
typeof
e moldes
Esses operadores e expressões executam verificação de tipo ou conversão de tipo. O is
operador verifica se o tipo de tempo de execução de uma expressão é compatível com um determinado tipo. O as
operador converte explicitamente uma expressão em um determinado tipo se seu tipo de tempo de execução for compatível com esse tipo. As expressões de transmissão executam uma conversão explícita para um tipo de destino. O typeof
operador obtém a System.Type instância para um tipo.
é operador
O is
operador verifica se o tipo de tempo de execução de um resultado de expressão é compatível com um determinado tipo. O is
operador também testa um resultado de expressão em relação a um padrão.
A expressão com o operador de teste is
de tipo tem a seguinte forma
E is T
onde E
é uma expressão que retorna um valor e T
é o nome de um tipo ou um parâmetro type. E
não pode ser um método anônimo ou uma expressão lambda.
O is
operador retorna true
quando um resultado de expressão é não-nulo e qualquer uma das seguintes condições são verdadeiras:
O tipo de tempo de execução de um resultado de expressão é
T
.O tipo de tempo de execução de um resultado de expressão deriva do tipo
T
, implementa a interfaceT
ou outra conversão de referência implícita existe dele paraT
.O tipo de tempo de execução de um resultado de expressão é um tipo de valor anulável com o tipo
T
subjacente e o Nullable<T>.HasValue istrue
.Existe uma conversão de boxe ou unboxing do tipo de tempo de execução de um resultado de expressão para o tipo
T
.
O is
operador não considera conversões definidas pelo usuário.
O exemplo a seguir demonstra que o is
operador retorna true
se o tipo de tempo de execução de um resultado de expressão deriva de um determinado tipo, ou seja, existe uma conversão de referência entre tipos:
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
}
}
O próximo exemplo mostra que o operador leva em conta as is
conversões de boxe e unboxing, mas não considera as conversões numéricas:
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
Para obter informações sobre conversões em C#, consulte o capítulo Conversões da especificação da linguagem C#.
Teste de tipo com correspondência de padrões
O is
operador também testa um resultado de expressão em relação a um padrão. O exemplo a seguir mostra como usar um padrão de declaração para verificar o tipo de tempo de execução de uma expressão:
int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
Console.WriteLine(a + b); // output 30
}
Para obter informações sobre os padrões suportados, consulte Padrões.
operador as
O as
operador converte explicitamente o resultado de uma expressão em uma determinada referência ou tipo de valor anulável. Se a conversão não for possível, o as
operador retornará null
. Ao contrário de uma expressão de elenco, o as
operador nunca lança uma exceção.
A expressão da forma
E as T
onde E
é uma expressão que retorna um valor e T
é o nome de um tipo ou um parâmetro type, produz o mesmo resultado que
E is T ? (T)(E) : (T)null
só que só é E
avaliado uma vez.
O as
operador considera apenas conversões de referência, anuláveis, boxe e unboxing. Não é possível usar o as
operador para executar uma conversão definida pelo usuário. Para fazer isso, use uma expressão de elenco.
O exemplo a seguir demonstra o uso do as
operador:
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
}
Nota
Como mostra o exemplo anterior, você precisa comparar o as
resultado da expressão com null
para verificar se a conversão foi bem-sucedida. Você pode usar o operador is para testar se a conversão é bem-sucedida e, se for bem-sucedida, atribuir seu resultado a uma nova variável.
Expressão de elenco
Uma expressão de conversão do formulário (T)E
executa uma conversão explícita do resultado da expressão E
em tipo T
. Se não existir nenhuma conversão explícita do tipo para o tipoT
, ocorrerá um erro em tempo de E
compilação. Em tempo de execução, uma conversão explícita pode não ter êxito e uma expressão de elenco pode lançar uma exceção.
O exemplo a seguir demonstra conversões numéricas e de referência explícitas:
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
Para obter informações sobre conversões explícitas suportadas, consulte a seção Conversões explícitas da especificação da linguagem C#. Para obter informações sobre como definir uma conversão de tipo explícita ou implícita personalizada, consulte Operadores de conversão definidos pelo usuário.
Outros usos de ()
Você também usa parênteses para chamar um método ou invocar um delegado.
Outro uso de parênteses é ajustar a ordem na qual avaliar operações em uma expressão. Para obter mais informações, consulte Operadores C#.
Tipo de operador
O typeof
operador obtém a System.Type instância para um tipo. O argumento para o typeof
operador deve ser o nome de um tipo ou um parâmetro type, como mostra o exemplo a seguir:
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]
O argumento não deve ser um tipo que exija anotações de metadados. Os exemplos incluem os seguintes tipos:
dynamic
string?
(ou qualquer tipo de referência anulável)
Esses tipos não são representados diretamente nos metadados. Os tipos incluem atributos que descrevem o tipo subjacente. Em ambos os casos, você pode usar o tipo subjacente. Em vez de dynamic
, você pode usar object
. Em vez de string?
, você pode usar string
.
Você também pode usar o typeof
operador com tipos genéricos não acoplados. O nome de um tipo genérico não acoplado deve conter o número apropriado de vírgulas, que é um a menos do que o número de parâmetros de tipo. O exemplo a seguir mostra o typeof
uso do operador com um tipo genérico não acoplado:
Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]
Uma expressão não pode ser um argumento do typeof
operador. Para obter a System.Type instância para o tipo de tempo de execução de um resultado de expressão, use o Object.GetType método.
Ensaio de tipo com o typeof
operador
Use o typeof
operador para verificar se o tipo de tempo de execução do resultado da expressão corresponde exatamente a um determinado tipo. O exemplo a seguir demonstra a diferença entre a verificação de tipo feita com o typeof
operador e o operador 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
}
}
Capacidade de sobrecarga do operador
O is
, as
e typeof
os operadores não podem ser sobrecarregados.
Um tipo definido pelo usuário não pode sobrecarregar o ()
operador, mas pode definir conversões de tipo personalizadas que podem ser executadas por uma expressão de transmissão. Para obter mais informações, consulte Operadores de conversão definidos pelo usuário.
Especificação da linguagem C#
Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#: