Pattern matching em C#
As novas versões do C# trouxeram diversas novidades que melhoraram o nosso dia a dia escrevendo código.
A partir do C# 7 começaram a surgir recursos voltados para pattern matching. Um recurso importante são as expressões do tipo is
com padrões. Esse tipo de expressão tem diversas variações, mas eu vejo uma em particular causar um pouco de confusão em pessoas que não estão tão acostumadas com C# moderno.
Atualmente, validações de nulabilidade podem ser feitas assim
|
|
ou assim
|
|
Como tenho costume de escrever na primeira forma geralmente me perguntam qual a diferença entre as duas. Neste post tento explicar a diferença entre as duas comparações fazendo a análise do código IL gerado para os dois casos.
🛑 Spoiler (ou TL;DR): não há diferença nenhuma na maioria dos casos, o cenário muda quando é feita a sobrecarga dos operadores de igualdade em alguma classe.
Diferença entre as formas de comparação
Para analisar o IL gerado em ambos os casos, usei o código abaixo.
|
|
O resultado em ambos os casos foi o mesmo.
|
|
💡 Explicando (brevemente) as instruções
ldarg.1
: carrega o primeiro argumento do método para a pilhaldnull
: carrega o valornull
para a pilhaceq
: compara os valores da pilha e carrega 1 caso sejam iguais ou 0 caso contrário - esta instrução é a comparação propriamente dita
Com isso é possível concluir que não há diferença entre as duas formas de comparação, pelo menos na maioria dos casos.
Sobrecarregando o operador de igualdade
Caso o operador de igualdade (==
) seja sobrecarregado em alguma classe para conter uma lógica própria, o cenário muda um pouco.
Considerando a classe Numero
com o código abaixo
|
|
E os métodos de teste C3
e C4
|
|
Para o método C3
o IL gerado é diferente do anterior
|
|
A linha IL_0002
, como esperado, ao invés de usar a instrução ceq
usa a sobrecarga definida na classe Numero
.
Entretanto, no método C3
o código IL gerado é o mesmo dos exemplos anteriores.
|
|
Concluindo
O is null
, por bem ou por mal, não faz uso do operador sobrecarregado e, portanto, não está sujeito a possíveis erros de implementação ou mesmo uma implementação maliciosa. Embora estes casos sejam difíceis de serem encontrados no dia a dia, este é um efeito colateral interessante na minha opinião.
No código da classe de exemplo o operador de igualdade contém um código problemático sempre retornando true
, desta forma, uma comparação do tipo == null
vai retornar true
mesmo para uma instância válida, enquanto o retorno da expressão is null
será false para instâncias válidas.
|
|
O código usado nos exemplos pode ser encontrado no SharpLab.