Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Como os objetos são polimórficos, é possível que uma variável de um tipo de classe base mantenha um tipo derivado. Para acessar os membros da instância do tipo derivado, é necessário converter o valor de volta para o tipo derivado. No entanto, uma conversão cria o risco de lançar um InvalidCastException. O C# fornece declarações de correspondência de padrões que executam uma conversão condicionalmente somente quando ela for bem-sucedida. O C# também fornece os operadores is e as para testar se um valor é de um determinado tipo.
O exemplo a seguir mostra como usar a instrução is
de correspondência de padrões:
var g = new Giraffe();
var a = new Animal();
FeedMammals(g);
FeedMammals(a);
// Output:
// Eating.
// Animal is not a Mammal
SuperNova sn = new SuperNova();
TestForMammals(g);
TestForMammals(sn);
// Output:
// I am an animal.
// SuperNova is not a Mammal
static void FeedMammals(Animal a)
{
if (a is Mammal m)
{
m.Eat();
}
else
{
// variable 'm' is not in scope here, and can't be used.
Console.WriteLine($"{a.GetType().Name} is not a Mammal");
}
}
static void TestForMammals(object o)
{
// You also can use the as operator and test for null
// before referencing the variable.
var m = o as Mammal;
if (m != null)
{
Console.WriteLine(m.ToString());
}
else
{
Console.WriteLine($"{o.GetType().Name} is not a Mammal");
}
}
class Animal
{
public void Eat() { Console.WriteLine("Eating."); }
public override string ToString()
{
return "I am an animal.";
}
}
class Mammal : Animal { }
class Giraffe : Mammal { }
class SuperNova { }
O exemplo anterior demonstra alguns recursos de sintaxe de correspondência de padrões. A if (a is Mammal m)
instrução combina o teste com uma atribuição de inicialização. A atribuição ocorre somente quando o teste é bem-sucedido. A variável m
está somente no escopo na instrução if
inserida em ela foi atribuída. Você não pode acessar m
mais tarde no mesmo método. O exemplo anterior também mostra como usar o as
operador para converter um objeto em um tipo especificado.
Você também pode usar a mesma sintaxe para testar se um tipo de valor anulável tiver um valor, conforme mostrado no exemplo a seguir:
int i = 5;
PatternMatchingNullable(i);
int? j = null;
PatternMatchingNullable(j);
double d = 9.78654;
PatternMatchingNullable(d);
PatternMatchingSwitch(i);
PatternMatchingSwitch(j);
PatternMatchingSwitch(d);
static void PatternMatchingNullable(ValueType? val)
{
if (val is int j) // Nullable types are not allowed in patterns
{
Console.WriteLine(j);
}
else if (val is null) // If val is a nullable type with no value, this expression is true
{
Console.WriteLine("val is a nullable type with the null value");
}
else
{
Console.WriteLine("Could not convert " + val.ToString());
}
}
static void PatternMatchingSwitch(ValueType? val)
{
switch (val)
{
case int number:
Console.WriteLine(number);
break;
case long number:
Console.WriteLine(number);
break;
case decimal number:
Console.WriteLine(number);
break;
case float number:
Console.WriteLine(number);
break;
case double number:
Console.WriteLine(number);
break;
case null:
Console.WriteLine("val is a nullable type with the null value");
break;
default:
Console.WriteLine("Could not convert " + val.ToString());
break;
}
}
O exemplo anterior demonstra outros recursos de correspondência de padrões a serem usados com conversões. Você pode testar uma variável para o padrão nulo verificando especificamente o null
valor. Quando o valor do runtime da variável é null
, uma instrução is
que verifica um tipo sempre retorna false
. A instrução de correspondência de padrões is
não permite um tipo de valor anulável, como int?
ou Nullable<int>
, mas você pode testar para qualquer outro tipo de valor. Os is
padrões do exemplo anterior não são limitados aos tipos de valor anuláveis. Você também pode usar esses padrões para testar se uma variável de um tipo de referência tem um valor ou se é null
.
O exemplo anterior também mostra como você usa o padrão de tipo em uma switch
instrução em que a variável pode ser um dos muitos tipos diferentes.
Se você quiser testar se uma variável é de um determinado tipo, mas não atribuí-la a uma nova variável, você pode usar os operadores is
e as
para tipos de referência e tipos de valor anuláveis. O código a seguir mostra como usar as instruções is
e as
que faziam parte da linguagem C# antes da correspondência de padrões ser introduzida para testar se uma variável é de um determinado tipo:
// Use the is operator to verify the type.
// before performing a cast.
Giraffe g = new();
UseIsOperator(g);
// Use the as operator and test for null
// before referencing the variable.
UseAsOperator(g);
// Use pattern matching to test for null
// before referencing the variable
UsePatternMatchingIs(g);
// Use the as operator to test
// an incompatible type.
SuperNova sn = new();
UseAsOperator(sn);
// Use the as operator with a value type.
// Note the implicit conversion to int? in
// the method body.
int i = 5;
UseAsWithNullable(i);
double d = 9.78654;
UseAsWithNullable(d);
static void UseIsOperator(Animal a)
{
if (a is Mammal)
{
Mammal m = (Mammal)a;
m.Eat();
}
}
static void UsePatternMatchingIs(Animal a)
{
if (a is Mammal m)
{
m.Eat();
}
}
static void UseAsOperator(object o)
{
Mammal? m = o as Mammal;
if (m is not null)
{
Console.WriteLine(m.ToString());
}
else
{
Console.WriteLine($"{o.GetType().Name} is not a Mammal");
}
}
static void UseAsWithNullable(System.ValueType val)
{
int? j = val as int?;
if (j is not null)
{
Console.WriteLine(j);
}
else
{
Console.WriteLine("Could not convert " + val.ToString());
}
}
class Animal
{
public void Eat() => Console.WriteLine("Eating.");
public override string ToString() => "I am an animal.";
}
class Mammal : Animal { }
class Giraffe : Mammal { }
class SuperNova { }
Como você pode ver comparando esse código com o código de correspondência de padrões, a sintaxe de correspondência de padrões fornece recursos mais robustos combinando o teste e a atribuição em uma única instrução. Use a sintaxe de correspondência de padrões sempre que possível.