Percebi que Resharper sugere que eu mude este:
if (myObj.myProp is MyType)
{
...
}
nisso:
var myObjRef = myObj.myProp as MyType;
if (myObjRef != null)
{
...
}
Por que sugeriria essa mudança? Estou acostumado a Resharper sugerindo mudanças de otimização e mudanças de redução de código, mas parece que ele quer pegar minha única instrução e transformá-la em duas linhas.
De acordo com o MSDN :
Uma expressão is avaliada como verdadeira se as seguintes condições forem atendidas:
expressão não é nula. a expressão pode ser convertida em tipo . Ou seja, uma expressão de conversão do formulário
(type)(expression)
será concluída sem lançar uma exceção.
Estou interpretando mal isso ou não is
faço exatamente as mesmas verificações, apenas em uma única linha, sem a necessidade de criar explicitamente outra variável local para a verificação nula?
MyProp
getter após essa mudança.Respostas:
Porque há apenas um elenco. Compare isto:
para isso:
C # 7.0 oferece suporte a uma sintaxe mais compacta usando correspondência de padrões :
fonte
as
pode ser alguns nanossegundos mais rápido, mas considero isso uma microotimização prematura.myObj
oumyProp
pode ser alterado (por outro encadeamento) entre ois
e o elenco, causando um comportamento indesejável.as
+!= null
também executará o!=
operador substituído deMyType
se definido (mesmo semyObjRef
for nulo). Embora na maioria dos casos isso não seja um problema (especialmente se você implementá-lo corretamente), em alguns casos extremos (código ruim, desempenho) pode não ser desejado. (teria que ser muito extremo, no entanto)object.ReferenceEquals(null, myObjRef)
.A melhor opção é usar a correspondência de padrões assim:
fonte
Não há informações ainda sobre o que realmente acontece abaixo da cintura. Dê uma olhada neste exemplo:
Isso se traduz no seguinte IL:
O que importa aqui são as chamadas
isinst
ecastclass
- ambas relativamente caras. Se você comparar isso com a alternativa, verá que só faz umaisinst
verificação:Também vale a pena mencionar que um tipo de valor usará em
unbox.any
vez decastclass
:Observe, entretanto, que isso não se traduz necessariamente em um resultado mais rápido, como podemos ver aqui . Não parece ter havido melhorias desde que pergunta foi feita, porém: moldes parecem ser realizada o mais rápido que costumava ser, mas
as
elinq
agora são cerca de 3 vezes mais rápido.fonte
Aviso de recompactação:
"Type check and direct cast can be replaced with try cast and check for null"
Ambos funcionarão, depende de como seu código se adapta melhor a você. No meu caso, simplesmente ignoro esse aviso:
No meu código, a segunda forma é mais longa e pior.
fonte
IRunable
. Se você não tem o controle, talvez possa usardynamic
?Para mim, isso parece dependente de quais são as chances de que seja desse tipo ou não. Certamente seria mais eficiente fazer o elenco logo de cara se o objeto fosse desse tipo na maioria das vezes. Se for desse tipo apenas ocasionalmente, pode ser mais adequado verificar primeiro com is.
O custo de criação de uma variável local é muito insignificante em comparação com o custo da verificação de tipo.
Legibilidade e escopo são os fatores mais importantes para mim normalmente. Eu discordaria do ReSharper e usaria o operador "é" apenas por esse motivo; otimize mais tarde se for um verdadeiro gargalo.
(Presumo que você esteja usando apenas
myObj.myProp is MyType
uma vez nesta função)fonte
Deve estar sugerindo uma segunda mudança também:
para dentro
Isso salva um acesso à propriedade e um elenco, em comparação com o código original. Mas só é possível depois de mudar
is
paraas
.fonte
(MyType)
lançará uma exceção se a conversão falhar.as
só retornanull
.is
(esse código está em questão).Eu diria que isso é para fazer uma versão fortemente tipada de myObj.myProp, que é myObjRef. Isso deve ser usado quando você está referenciando esse valor no bloco, em vez de ter que fazer uma conversão.
Por exemplo, este:
é melhor do que isso:
fonte