Operadores de teste de tipo e expressões de molde - is, astypeof 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 interface Tou outra conversão de referência implícita existe dele para T.

  • 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 is true.

  • 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, ase 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#:

Consulte também