Considere el siguiente código:
void Handler(object o, EventArgs e)
{
// I swear o is a string
string s = (string)o; // 1
//-OR-
string s = o as string; // 2
// -OR-
string s = o.ToString(); // 3
}
¿Cuál es la diferencia entre los tres tipos de lanzamiento (está bien, el tercero no es un lanzamiento, pero se obtiene la intención). ¿Cuál debería ser el preferido?
string s = Convert.ToString(o)
:; 5to:string s = $"{o}"
(o equivalentemente elstring.Format
formulario para C # anterior)Respuestas:
Lanza InvalidCastException si
o
no es unstring
. De lo contrario, se asignao
as
, incluso sio
es asínull
.Asigna
null
as
sio
no es unstring
o sio
esnull
. Por esta razón, no puede usarlo con tipos de valor (el operador nunca podría regresarnull
en ese caso). De lo contrario, se asignao
as
.Causa una NullReferenceException si
o
esnull
. Asigna lo que sea queo.ToString()
regreses
, sin importar de qué tipoo
sea.Use 1 para la mayoría de las conversiones: es simple y directo. Casi nunca uso 2 ya que si algo no es del tipo correcto, generalmente espero que ocurra una excepción. Solo he visto la necesidad de este tipo de funcionalidad de retorno nulo con bibliotecas mal diseñadas que usan códigos de error (por ejemplo, retorno nulo = error, en lugar de usar excepciones).
3 no es un elenco y es solo una invocación de método. Úselo para cuando necesite la representación de cadena de un objeto que no sea de cadena.
fuente
string s = (string)o;
Úselo cuando algo definitivamente debería ser lo otro.string s = o as string;
Úselo cuando algo podría ser lo otro.string s = o.ToString();
Úselo cuando no le importe lo que es, pero solo desea utilizar la representación de cadena disponible.fuente
Realmente depende de si sabes si
o
es una cadena y qué quieres hacer con ella. Si su comentario significa queo
realmente es una cadena, preferiría el(string)o
reparto directo , es poco probable que falle.La mayor ventaja de usar el lanzamiento directo es que cuando falla, obtienes una InvalidCastException , que te dice más o menos lo que salió mal.
Con el
as
operador, sio
no es una cadena,s
se establece ennull
, lo cual es útil si no está seguro y desea probars
:Sin embargo, si no realiza esa prueba, la usará
s
más tarde y se generará una excepción NullReferenceException . Estos tienden a ser más comunes y mucho más difíciles de rastrear una vez que ocurren en la naturaleza, ya que casi todas las líneas desreferencian una variable y pueden arrojar una. Por otro lado, si está intentando convertir a un tipo de valor (cualquier primitivo, o estructuras como DateTime ), debe usar la conversión directa;as
no funcionará.En el caso especial de convertir a una cadena, cada objeto tiene un
ToString
, por lo que su tercer método puede estar bien sio
no es nulo y cree que elToString
método podría hacer lo que desea.fuente
as
con tipos de valores anulables . IEo as DateTime
no funcionará, peroo as DateTime?
...if (s is string)
lugar?is
ing, tendrá que lanzar de nuevo de todos modos, por lo que tiene el is y luego un yeso duro. Por alguna razón, elas
cheque nulo me pareció mejor.Si ya sabe a qué tipo puede emitir, use un molde de estilo C:
Tenga en cuenta que solo con un elenco de estilo C puede realizar una coerción de tipo explícito.
Si no sabe si es el tipo deseado y lo va a usar si es así, use como palabra clave:
Tenga en cuenta que como no llamará a ningún tipo de operadores de conversión. Solo será no nulo si el objeto no es nulo y es nativo del tipo especificado.
Use ToString () para obtener una representación de cadena legible por humanos de cualquier objeto, incluso si no se puede convertir en cadena.
fuente
La palabra clave as es buena en asp.net cuando usa el método FindControl.
Esto significa que puede operar en la variable escrita en lugar de tener que emitirla
object
como lo haría con una conversión directa:No es una gran cosa, pero guarda líneas de código y asignación de variables, además es más legible
fuente
'as' se basa en 'is', que es una palabra clave que verifica en tiempo de ejecución si el objeto es polimorfológicamente compatible (básicamente, si se puede realizar una conversión) y devuelve nulo si la verificación falla.
Estos dos son equivalentes:
Usando 'como':
Usando 'es':
Por el contrario, el elenco de estilo c también se realiza en tiempo de ejecución, pero arroja una excepción si no se puede realizar el elenco.
Solo para agregar un hecho importante:
La palabra clave 'as' solo funciona con tipos de referencia. Tú no puedes hacer:
En esos casos tienes que usar casting.
fuente
2 es útil para convertir a un tipo derivado.
Supongamos que a es un animal:
obtendrá una alimentación con un mínimo de yesos.
fuente
Según los experimentos realizados en esta página: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as
(esta página tiene algunos errores de "referencia ilegal" a veces, así que simplemente actualice si es así)
La conclusión es que el operador "como" es normalmente más rápido que un yeso. A veces muchas veces más rápido, a veces apenas más rápido.
Peronsonally cosa "como" también es más legible.
Entonces, dado que es más rápido y "más seguro" (no arrojará una excepción), y posiblemente más fácil de leer, recomiendo usar "como" todo el tiempo.
fuente
"(string) o" dará como resultado una InvalidCastException ya que no hay conversión directa.
"o como cadena" dará como resultado que s sea una referencia nula, en lugar de que se genere una excepción.
"o.ToString ()" no es un elenco de ningún tipo en sí, es un método implementado por objeto y, por lo tanto, de una forma u otra, por cada clase en .net que "hace algo" con la instancia de se llama a la clase y devuelve una cadena.
No olvide que para convertir a cadena, también hay Convert.ToString (someType instanceOfThatType) donde someType es uno de un conjunto de tipos, esencialmente los tipos base de frameworks.
fuente
Todas las respuestas dadas son buenas, si pudiera agregar algo: para usar directamente los métodos y propiedades de la cadena (por ejemplo, ToLower) no puede escribir:
solo puedes escribir:
pero podrías escribir en su lugar:
La
as
opción es más legible (al menos en mi opinión).fuente
(o as string).ToLower()
lugar de los múltiples corchetes confusos.Se prefiere, ya que evita la penalización de rendimiento de doble lanzamiento.
fuente
Parece que los dos son conceptualmente diferentes.
Fundición directa
Los tipos no tienen que estar estrictamente relacionados. Viene en todo tipo de sabores.
Parece que el objeto se va a convertir en otra cosa.
Operador AS
Los tipos tienen una relación directa. Como en:
Parece que vas a manejar el objeto de una manera diferente.
Muestras e IL
fuente
Me gustaría llamar la atención sobre los siguientes detalles del operador as :
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/as
fuente
Al intentar obtener la representación de cadena de cualquier cosa (de cualquier tipo) que podría ser nula, prefiero la siguiente línea de código. Es compacto, invoca ToString () y maneja correctamente los valores nulos. Si o es nulo, s contendrá String.Empty.
fuente
Como nadie lo mencionó, la palabra clave más cercana a la instancia de Java es esta:
fuente
Utilice la conversión directa
string s = (string) o;
si en el contexto lógico de su aplicaciónstring
es el único tipo válido. Con este enfoque, obtendráInvalidCastException
e implementará el principio de Fail-fast . Su lógica estará protegida para que no pase más el tipo no válido u obtenga NullReferenceException si se utiliza elas
operador.Si la lógica espera varios tipos diferentes de conversión
string s = o as string;
y verifíquelonull
o use elis
operador.Nueva característica fresca han aparecido en C # 7.0 para simplificar el elenco y el cheque es una comparación de patrones :
fuente
Las siguientes dos formas de conversión de tipos (conversión) se admiten en C #:
El |
(CV
• Convertir el tipo estático de v a c en la expresión dada
• Solo es posible si el tipo dinámico de v es c, o un subtipo de c
• Si no, se lanza una InvalidCastException
El |
v como C
• Variante no fatal de (c) v
• Por lo tanto, convierta el tipo estático de v a c en la expresión dada
• Devuelve nulo si el tipo dinámico de v no es c, o un subtipo de c
fuente