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 operador is
verifica se o tipo de runtime de uma expressão é compatível com um determinado tipo. O operador as
converte uma expressão explicitamente para determinado tipo se o tipo do respectivo runtime for compatível com o tipo em questão. As expressões de conversão executam uma conversão explícita para um tipo de destino. O operador typeof
obtém a instância System.Type para um tipo.
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
em que E
é 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 do resultado de uma expressão em tempo de execução é
T
.O tipo do resultado de uma expressão em tempo de execução deriva do tipo
T
, implementa a interfaceT
ou existe outra conversão de referência implícita dele paraT
.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 boxing ou uma conversão unboxing do tipo do resultado de uma expressão em tempo de execução para o tipo
T
.
O operador is
não considera conversões definidas pelo usuário.
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.
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
em que E
é 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 mostrado no exemplo anterior, você precisa comparar o resultado da expressão as
com null
para verificar se uma conversão foi bem-sucedida. Você pode usar o operador is para testar se a conversão foi 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#.
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 seguinte exemplo demonstra as diferenças entre as verificações de tipo executadas com o operador typeof
e com 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
Os operadores is
, as
e typeof
não podem ser sobrecarregados.
Um tipo definido pelo usuário não pode criar uma sobrecarregar para o operador ()
, mas pode definir conversões de tipo personalizadas, que podem ser executadas por uma expressão de conversão. 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#: