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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top