Fundição:(NovoTipo) vs.Objeto como NewType [duplicado]
Pergunta
Possível duplicata:
Transmitir vs usar a palavra-chave 'as' no CLR
Qual é realmente a diferença entre esses dois elencos?
SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;
Normalmente, ambos deveriam ser conversões explícitas para o tipo especificado?
Solução
O primeiro lançará uma exceção se o tipo de origem não puder ser convertido no tipo de destino.O último resultará em sc2 sendo uma referência nula, mas sem exceção.
[Editar]
Minha resposta original é certamente a diferença mais pronunciada, mas como Eric Lippert aponta, não é o único.Outras diferenças incluem:
- Você não pode usar o operador 'as' para converter para um tipo que não aceita 'null' como valor
- Você não pode usar 'as' para converter coisas, como números, para uma representação diferente (float para int, por exemplo).
E finalmente, usando 'as' vs.o operador de elenco, você também está dizendo "Não tenho certeza se isso terá sucesso".
Outras dicas
Observe também que você só pode usar a palavra-chave as com um tipo de referência ou um tipo anulável
ou seja:
double d = 5.34;
int i = d as int;
não irá compilar
double d = 5.34;
int i = (int)d;
irá compilar.
A conversão de tipo usando "as" é obviamente muito mais rápida quando a conversão falha, pois evita a despesa de lançar uma exceção.
Mas não é mais rápido quando o lançamento é bem-sucedido.O gráfico em http://www.codeproject.com/KB/cs/csharpcasts.aspx é enganoso porque não explica o que está medindo.
O resultado final é:
Se você espera que o elenco tenha sucesso (ou seja,uma falha seria excepcional), use um elenco.
Se você não sabe se terá sucesso, use o operador "as" e teste o resultado para nulo.
Uma diferença entre as duas abordagens é que a primeira ((SomeClass)obj) pode causar um conversor de tipo ser chamado.
Esta é uma boa maneira de lembrar o processo que cada um deles segue e que utilizo ao tentar decidir o que é melhor para minha situação.
DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);
e o próximo deve ser fácil de adivinhar o que faz
DateTime i = value as DateTime;
no primeiro caso, se o valor não puder ser convertido, uma exceção será lançada; no segundo caso, se o valor não puder ser convertido, i será definido como nulo.
Portanto, no primeiro caso, uma parada brusca é feita, se a conversão falhar, na segunda conversão, uma parada suave é feita e você pode encontrar uma NullReferenceException posteriormente.
Bem o operador 'as' "ajuda" você a enterrar seu problema bem mais fundo porque quando for fornecida uma instância incompatível ele retornará nulo, talvez você passe isso para um método que irá passá-lo para outro e assim por diante e finalmente você obterá uma NullReferenceException que tornará sua depuração mais difícil.
Não abuse.O operador de conversão direta é melhor em 99% dos casos.
Para expandir Comentário de Rytmis, você não pode usar o como palavra-chave para estruturas (tipos de valor), pois elas não possuem valor nulo.
Tudo isso se aplica a tipos de referência, os tipos de valor não podem usar o as
palavra-chave, pois não podem ser nulos.
//if I know that SomeObject is an instance of SomeClass
SomeClass sc = (SomeClass) someObject;
//if SomeObject *might* be SomeClass
SomeClass sc2 = someObject as SomeClass;
A sintaxe de conversão é mais rápida, mas somente quando bem-sucedida é muito mais lenta para falhar.
A melhor prática é usar as
quando você não conhece o tipo:
//we need to know what someObject is
SomeClass sc;
SomeOtherClass soc;
//use as to find the right type
if( ( sc = someObject as SomeClass ) != null )
{
//do something with sc
}
else if ( ( soc = someObject as SomeOtherClass ) != null )
{
//do something with soc
}
No entanto, se você tiver certeza absoluta de que someObject
é um exemplo de SomeClass
então use elenco.
No .Net 2 ou superior, genéricos significam que muito raramente você precisa ter uma instância não digitada de uma classe de referência, portanto, a última é usada com menos frequência.
A conversão entre parênteses lança uma exceção se a tentativa de conversão falhar.A conversão "as" retorna nulo se a tentativa de conversão falhar.
Eles lançarão exceções diferentes.
():Exceção de Referência Nula
como :InvalidCastException
O que pode ajudar na depuração.
A palavra-chave "as" tenta converter o objeto e se a conversão falhar, null será retornado silenciosamente.O operador de conversão () lançará uma exceção imediatamente se a conversão falhar.
"Use apenas a palavra-chave "as" do C# quando você espera que a conversão falhe em um caso não excepcional.Se você está contando com o sucesso de uma conversão e não está preparado para receber qualquer objeto que possa falhar, você deve usar o operador de conversão () para que uma exceção apropriada e útil seja lançada."
Para exemplos de código e uma explicação adicional: http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html
É como a diferença entre Parse e TryParse.Você usa o TryParse quando espera que ele falhe, mas quando tiver uma forte garantia de que não falhará, use o Parse.
Para aqueles com experiência em VB.NET, (type) é o mesmo que DirectCast e "as type" é o mesmo que TryCast.