Ao manipular objetos cujas classes derivam de um mesmo tipo básico é extremamente comum se recorrer a checagens empregando o operador is. Também são frequentes operações de typecast indicando o uso de uma estrutura requerida por um contexto específico.
Para exemplificar isto serão utilizadas as seguintes classes:
- Cotacao, tipo abstrato que representa uma cotação de moeda estrangeira;
- CotacaoDolar, implementação concreta baseada em Cotacao e contendo informações da cotação do dólar norte-americano em uma data (tanto o valor comercial, quanto o correspondente para fins de turismo);
- CotacaoEuro, com dados relativos a uma cotação do euro.
using System;
namespace ExemploPatternMatching
{
public abstract class Cotacao
{
public DateTime DataCotacao { get; set; }
public abstract string SiglaMoeda { get; }
public abstract string NomeMoeda { get; }
}
public class CotacaoDolar : Cotacao
{
public override string SiglaMoeda
{ get { return "Dólar norte-americano"; } }
public override string NomeMoeda
{ get { return "USD"; } }
public double ValorComercial { get; set; }
public double ValorTurismo { get; set; }
}
public class CotacaoEuro : Cotacao
{
public override string SiglaMoeda
{ get { return "Euro"; } }
public override string NomeMoeda
{ get { return "EUR"; } }
public double ValorCotacao { get; set; }
}
}
Na próxima listagem está a definição de um método chamado ExibirInformacoesCotacao:
- Esta operação receberá como parâmetro uma instância do tipo Cotacao, a fim de exibir informações sobre uma moeda estrangeira;
- Um único valor de cotação será mostrado. Para referências baseadas em CotacaoEuro este dado se encontra na propriedade ValorCotacao. Já para o tipo CotacaoDolar será assumido o valor associado à propriedade ValorComercial. Até o C# 6.0 todo este processo acontecia empregando o operador is, além de incluir casts quando fosse necessário manipular implementações mais específicas da classe-base.
public static void ExibirInformacoesCotacao(Cotacao cotacao)
{
double valorCotacao = 0;
if (cotacao is CotacaoDolar)
{
valorCotacao =
((CotacaoDolar)cotacao).ValorComercial;
}
else if (cotacao is CotacaoEuro)
{
valorCotacao =
((CotacaoEuro)cotacao).ValorCotacao;
}
Console.WriteLine(new String('-', 40));
Console.WriteLine($"Data: {cotacao.DataCotacao:dd/MM/yyyy}");
Console.WriteLine($"Sigla: {cotacao.SiglaMoeda}");
Console.WriteLine($"Moeda: {cotacao.NomeMoeda}");
Console.WriteLine($"Valor: {valorCotacao:0.0000}");
}
A seguir é possível observar um exemplo de uso do recurso de Pattern Matching (após a refatoração do método ExibirInformacoesCotacao):
- Esta funcionalidade permite definir uma variável em conjunto com o operador is, com a mesma sendo preenchida caso a referência em análise corresponda ao tipo que se está verificando;
- A vantagem deste novo mecanismo está em eliminar a necessidade de codificação de um typecast, contribuindo assim para um código mais limpo e direto.
using System;
namespace ExemploPatternMatching
{
class Program
{
public static void ExibirInformacoesCotacao(Cotacao cotacao)
{
double valorCotacao = 0;
if (cotacao is CotacaoDolar dolar)
valorCotacao = dolar.ValorComercial;
else if (cotacao is CotacaoEuro euro)
valorCotacao = euro.ValorCotacao;
Console.WriteLine(new String('-', 40));
Console.WriteLine($"Data: {cotacao.DataCotacao:dd/MM/yyyy}");
Console.WriteLine($"Sigla: {cotacao.SiglaMoeda}");
Console.WriteLine($"Moeda: {cotacao.NomeMoeda}");
Console.WriteLine($"Valor: {valorCotacao:0.0000}");
}
static void Main(string[] args)
{
CotacaoDolar dolar = new CotacaoDolar();
dolar.DataCotacao = new DateTime(2017, 3, 24);
dolar.ValorComercial = 3.1083;
dolar.ValorTurismo = 3.2700;
ExibirInformacoesCotacao(dolar);
CotacaoEuro euro = new CotacaoEuro();
euro.DataCotacao = new DateTime(2017, 3, 24);
euro.ValorCotacao = 3.3695;
ExibirInformacoesCotacao(euro);
Console.ReadKey();
}
}
}
A execução deste bloco de código apresentará como resultado:
O método ExibirInformacoesCotacao pode ainda ser refatorado, de forma a se fazer uso de um switch em conjunto com a funcionalidade de Pattern Matching:
public static void ExibirInformacoesCotacao(Cotacao cotacao)
{
double valorCotacao;
switch (cotacao)
{
case CotacaoDolar dolar:
valorCotacao = dolar.ValorComercial;
break;
case CotacaoEuro euro:
valorCotacao = euro.ValorCotacao;
break;
default:
valorCotacao = 0;
break;
}
Console.WriteLine(new String('-', 40));
Console.WriteLine($"Data: {cotacao.DataCotacao:dd/MM/yyyy}");
Console.WriteLine($"Sigla: {cotacao.SiglaMoeda}");
Console.WriteLine($"Moeda: {cotacao.NomeMoeda}");
Console.WriteLine($"Valor: {valorCotacao:0.0000}");
}









