Em C # 7, podemos usar
if (x is null) return;
ao invés de
if (x == null) return;
Existem vantagens em usar a nova maneira (exemplo anterior) em relação à maneira antiga?
A semântica é diferente?
É apenas uma questão de gosto? Caso contrário, quando devo usar um sobre o outro?
Referência: O que há de novo no C # 7.0 .
Respostas:
Atualização: o compilador Roslyn foi atualizado para tornar o comportamento dos dois operadores o mesmo quando não há um operador de igualdade sobrecarregado . Por favor, veja o código nos resultados atuais do compilador (
M1
eM2
no código) que mostra o que acontece quando não há comparador de igualdade sobrecarregado. Agora, ambos têm o==
comportamento com melhor desempenho . Se houver um comparador de igualdade sobrecarregado, o código ainda será diferente .Veja para versões mais antigas do compilador Roslyn a análise abaixo.
Pois
null
não há diferença com o que estamos acostumados com o C # 6. No entanto, as coisas se tornam interessantes quando você mudanull
para outra constante.Veja isso por exemplo:
O teste cede
a
. Se você comparar isso com oo == (object)1
que você escreveria normalmente, isso fará muita diferença.is
leva em consideração o tipo do outro lado da comparação. Isso é legal!Eu acho que o padrão
== null
vs.is null
constante é apenas algo que é muito familiar 'por acidente', em que a sintaxe dois
operador e do operador igual produz o mesmo resultado.Como svick comentou,
is null
chamaSystem.Object::Equals(object, object)
onde==
chamaceq
.IL para
is
:IL para
==
:Como estamos falando
null
, não há diferença, pois isso só faz diferença nas instâncias . Isso pode mudar quando você sobrecarrega o operador de igualdade.fonte
is
chamadasobject.Equals(x, null)
, enquanto==
compila comoceq
. Mas o resultado deve ser o mesmo, como você disse.==
é um operador sobrecarregável. Você pode ter qualquer comportamento que quiser com ele. Por exemplo, isso estranhamente implementado==
não informa se sua instância é realmente nula.is null
por outro lado, sempre retornará true para referências nulas verdadeiras :) Além disso, se você tiverReferenceEquals
em seu código, as lâmpadas do VS 2017 sugerem que você mude parais null
, não== null
(corretamente).is
não há mais a sobrecarga de uma chamada de função quando usada para verificar a nula. Para prova, veja o link postado por @svick nos comentários.Operador igual sobrecarregado
De fato, há uma diferença na semântica entre as duas comparações quando você está comparando
null
com um tipo que sobrecarregou o==
operador.foo is null
usará comparação direta de referência para determinar o resultado, enquanto,foo == null
é claro, executará o==
operador sobrecarregado , se ele existir.Neste exemplo, introduzi um "bug" no
==
operador sobrecarregado , fazendo com que ele sempre lança uma exceção se o segundo argumento fornull
:O código IL para
foo is null
usa aceq
instrução para executar uma comparação direta de referência:O código IL para
foo == null
usa uma chamada para o operador sobrecarregado:Portanto, a diferença é que, se você usar,
==
corre o risco de executar o código do usuário (que pode potencialmente ter problemas inesperados de comportamento ou desempenho).Restrição de genéricos
O uso da
is null
construção restringe o tipo a um tipo de referência. O compilador garante isso, o que significa que você não pode usaris null
em um tipo de valor. Se você tiver um método genérico, não poderá usá-lois null
, a menos que o tipo genérico seja restrito a ser um tipo de referência.Agradecemos a David Augusto Villa por apontar isso.
fonte