Compartilhar via


Operadores de teste de tipo e expressão de conversão is, as, typeof e conversões

Esses operadores e expressões executam a verificação de tipo ou a conversão de tipo. O isoperador verifica se o tipo do runtime de uma expressão é compatível com um determinado tipo. O asoperador converterá explicitamente uma expressão para determinado tipo se o tipo de runtime dele for compatível com esse tipo. As expressões de conversão executam uma conversão explícita para um tipo de destino. O typeofoperador obtém a instância System.Type para um tipo.

O operador is

O operador is verifica se o tipo do resultado de uma expressão em tempo de execução é compatível com determinado tipo. O operador is também testa um resultado de expressão em relação a um padrão.

A expressão com o operador is de teste de tipo tem o seguinte formato

E is T

Onde E está uma expressão que retorna um valor e T é o nome de um tipo ou um parâmetro de tipo. E não pode ser um método anônimo ou uma expressão lambda.

O operador is retorna true quando o resultado de uma expressão não é nulo e qualquer uma das seguintes condições é verdadeira:

  • O tipo de tempo de execução de um resultado de expressão tem uma conversão de identidade para T.

  • O tipo do resultado de uma expressão em tempo de execução deriva do tipo T, implementa a interface T ou existe outra conversão de referência implícita dele para T. Isso aborda relações de herança e implementações de interface.

  • O tipo do resultado de uma expressão em tempo de execução é um tipo de valor anulável com o tipo subjacente T e o Nullable<T>.HasValue é true.

  • Existe uma conversão de boxing ou unboxing do tipo de tempo de execução de um resultado de expressão para o tipo T quando a expressão não é uma instância de ref struct.

O is operador não considera conversões definidas pelo usuário ou conversões de intervalo implícitas.

O seguinte exemplo demonstra que o operador is retorna true se o tipo do resultado de uma expressão em tempo de execução é derivado de 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 is leva em conta conversões boxing e unboxing, mas não considera 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 saber mais sobre conversões em C#, confira o capítulo Conversões da Especificação da linguagem C#.

Teste de tipo com correspondência de padrões

O operador is também testa um resultado de expressão em relação a um padrão. O seguinte exemplo mostra como usar um padrão de declaração para verificar o tipo de uma expressão em tempo de execuçã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 com suporte, confira Padrões.

O operador as

O operador as converte explicitamente o resultado de uma expressão para uma determinada referência ou tipo de valor anulável. Se a conversão não for possível, o operador as retornará null. Ao contrário de uma expressão de conversão, o operador as nunca gera uma exceção.

A expressão da forma

E as T

Onde E está uma expressão que retorna um valor e T é o nome de um tipo ou um parâmetro de tipo, produz o mesmo resultado que

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

Exceto que E é avaliado apenas uma vez.

O operador as considera apenas as conversões de referência, anulável, boxing e unboxing. Não é possível usar o operador as para executar uma conversão definida pelo usuário. Para fazer isso, use uma expressão de conversão.

O exemplo a seguir demonstra o uso do operador 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
}

Observação

Como mostra o exemplo anterior, você precisa comparar o resultado da as expressão null para verificar se a conversão foi bem-sucedida. Você pode usar o is operador para testar se a conversão é bem-sucedida e, se for bem-sucedida, atribuir seu resultado a uma nova variável.

Expressão de conversão

Uma expressão de conversão do formulário (T)E realiza uma conversão explícita do resultado da expressão E para o tipo T. Se não existir nenhuma conversão explícita do tipo E para o tipo T, ocorrerá um erro em tempo de compilação. No tempo de execução, uma conversão explícita pode não ter êxito e uma expressão de conversão 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 saber mais sobre conversões explícitas sem suporte, confira a seção Conversões explícitas da Especificação da linguagem C#. Para saber mais sobre como definir uma conversão de tipo explícito ou implícito personalizado, confira Operadores de conversão definidos pelo usuário.

Outros usos de ()

Você também usa parênteses para chamar um método ou chamar um delegado .

Outro uso dos parênteses é ajustar a ordem na qual as operações em uma expressão são avaliadas. Para saber mais, confira Operadores C#.

O operador typeof

O operador typeof obtém a instância System.Type para um tipo. O argumento do operador typeof deve ser o nome de um tipo ou um parâmetro de tipo, 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. Como exemplo, confira os seguintes tipos:

  • dynamic
  • string? (ou qualquer tipo de referência anulável)

Esses tipos não são representados diretamente em 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 operador typeof com tipos genéricos não associados. O nome de um tipo genérico não associado deve conter o número apropriado de vírgulas, que é um a menos que o número de parâmetros de tipo. O exemplo a seguir mostra o uso do operador typeof com um tipo genérico não associado:

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

O operador typeof não pode ter como argumento uma expressão. Para obter a instância System.Type para o tipo do resultado de uma expressão em tempo de execução, use o método Object.GetType.

Teste de tipo com o operador typeof

Use o operador typeof para verificar se o tipo do resultado da expressão em tempo de execução corresponde exatamente a determinado tipo. O exemplo a seguir demonstra a diferença entre a verificação de tipo feita com o typeof operador e o is operador:

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

Os operadores is, as e typeof 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, realizadas por meio de uma expressão de cast. Para saber mais, confira Operadores de conversão definidos pelo usuário.

Especificação da linguagem C#

Para obter mais informações, confira as seguintes seções da especificação da linguagem C#:

Veja também