A continuación se muestra una publicación del siguiente artículo :
A menudo se pasa por alto la diferencia entre coerción y casting. Puedo ver porque; muchos lenguajes tienen la misma (o similar) sintaxis y terminología para ambas operaciones. Algunos idiomas pueden incluso referirse a cualquier conversión como "conversión", pero la siguiente explicación se refiere a conceptos en el CTS.
Si está intentando asignar un valor de algún tipo a una ubicación de un tipo diferente, puede generar un valor del nuevo tipo que tenga un significado similar al original. Esto es coerción. La coerción le permite usar el nuevo tipo creando un nuevo valor que de alguna manera se parece al original. Algunas coacciones pueden descartar datos (por ejemplo, convertir el int 0x12345678 al corto 0x5678), mientras que otras pueden no (por ejemplo, convertir el int 0x00000008 al corto 0x0008, o el largo 0x0000000000000008).
Recuerde que los valores pueden tener varios tipos. Si su situación es ligeramente diferente y solo desea seleccionar uno diferente de los tipos de valor, el casting es la herramienta para el trabajo. La transmisión simplemente indica que desea operar en un tipo particular que incluye un valor.
La diferencia a nivel de código varía de C # a IL. En C #, tanto la conversión como la coerción se ven bastante similares:
static void ChangeTypes(int number, System.IO.Stream stream)
{
long longNumber = number;
short shortNumber = (short)number;
IDisposable disposableStream = stream;
System.IO.FileStream fileStream = (System.IO.FileStream)stream;
}
A nivel de IL son bastante diferentes:
ldarg.0
conv.i8
stloc.0
ldarg.0
conv.i2
stloc.1
ldarg.1
stloc.2
ldarg.1
castclass [mscorlib]System.IO.FileStream
stloc.3
En cuanto al nivel lógico, existen algunas diferencias importantes. Lo más importante a recordar es que la coerción crea un nuevo valor, mientras que el casting no lo hace. La identidad del valor original y el valor después del lanzamiento son los mismos, mientras que la identidad de un valor coaccionado difiere del valor original; la coersión crea una instancia nueva y distinta, mientras que la conversión no lo hace. Un corolario es que el resultado del casting y el original siempre serán equivalentes (tanto en identidad como en igualdad), pero un valor coaccionado puede o no ser igual al original, y nunca comparte la identidad original.
Es fácil ver las implicaciones de la coerción en los ejemplos anteriores, ya que los tipos numéricos siempre se copian por valor. Las cosas se complican un poco cuando se trabaja con tipos de referencia.
class Name : Tuple<string, string>
{
public Name(string first, string last)
: base(first, last)
{
}
public static implicit operator string[](Name name)
{
return new string[] { name.Item1, name.Item2 };
}
}
En el siguiente ejemplo, una conversión es un reparto, mientras que la otra es una coerción.
Tuple<string, string> tuple = name;
string[] strings = name;
Después de estas conversiones, la tupla y el nombre son iguales, pero las cadenas no son iguales a ninguno de ellos. Puede hacer que la situación sea un poco mejor (o un poco más confusa) implementando Equals () y operator == () en la clase Name para comparar un Name y una cadena []. Estos operadores "arreglarían" el problema de comparación, pero aún tendría dos instancias separadas; cualquier modificación de las cadenas no se reflejaría en el nombre o la tupla, mientras que los cambios en el nombre o la tupla se reflejarían en el nombre y la tupla, pero no en las cadenas.
Aunque el ejemplo anterior estaba destinado a ilustrar algunas diferencias entre conversión y coerción, también sirve como un gran ejemplo de por qué debe ser extremadamente cauteloso al usar operadores de conversión con tipos de referencia en C #.