He visto que ambos términos se usan casi indistintamente en varias explicaciones en línea, y la mayoría de los libros de texto que he consultado tampoco son del todo claras sobre la distinción.
¿Existe quizás una forma clara y sencilla de explicar la diferencia que ustedes conocen?
Conversión de tipos (también conocida como conversión de tipos )
Utilizar un valor de un tipo en un contexto que espera otro.
Reparto de tipo no convertible (a veces conocido como retruécano )
Un cambio que no altera los bits subyacentes.
Coerción
Proceso por el cual un compilador convierte automáticamente un valor de un tipo en un valor de otro tipo cuando ese segundo tipo es requerido por el contexto circundante.
Respuestas:
Tipo de conversión :
Entonces, la coerción es implícita, el reparto es explícito y la conversión es cualquiera de ellos.
Algunos ejemplos (de la misma fuente ):
Coerción (implícita):
double d; int i; if (d > i) d = i;
Reparto (explícito):
double da = 3.3; double db = 3.3; double dc = 3.4; int result = (int)da + (int)db + (int)dc; //result == 9
fuente
Los usos varían, como nota.
Mis usos personales son:
Un "reparto" es el uso de un operador de reparto . Un operador de conversión le indica al compilador que (1) no se sabe que esta expresión sea del tipo dado, pero le prometo que el valor será de ese tipo en tiempo de ejecución; el compilador debe tratar la expresión como si fuera del tipo dado, y el tiempo de ejecución producirá un error si no lo es, o (2) la expresión es de un tipo completamente diferente, pero hay una forma bien conocida de asociar instancias del tipo de expresión con instancias del tipo de conversión. Se indica al compilador que genere código que realice la conversión. El lector atento notará que estos son opuestos, lo que creo que es un buen truco.
Una "conversión" es una operación mediante la cual un valor de un tipo se trata como un valor de otro tipo, generalmente un tipo diferente, aunque una "conversión de identidad" sigue siendo una conversión, técnicamente hablando. La conversión puede ser "cambio de representación", como int a double, o puede ser "preservación de representación" como cadena a objeto. Las conversiones pueden ser "implícitas", que no requieren una conversión, o "explícitas", que sí requieren una conversión.
Una "coerción" es una conversión implícita que cambia de representación.
fuente
Data.Coerce.coerce :: Coercible a b => a -> b
funciona para tipos que se ha demostrado que tienen la misma representación;Unsafe.Coerce.unsafeCoerce :: a -> b
funciona para dos tipos cualesquiera (y hará que los demonios salgan de su nariz si lo usa mal).La conversión es el proceso mediante el cual se trata un tipo de objeto como otro tipo, la coerción es convertir un objeto en otro.
Tenga en cuenta que en el proceso anterior no hay conversión involucrada, tiene un tipo que le gustaría tratar como otro, digamos, por ejemplo, tiene 3 objetos diferentes que heredan de un tipo base, y tiene un método que tomará ese tipo base, en cualquier momento, si conoce el tipo secundario específico, puede CAST lo que es y usar todos los métodos y propiedades específicos de ese objeto y eso no creará una nueva instancia del objeto.
Por otro lado, la coerción implica la creación de un nuevo objeto en la memoria del nuevo tipo y luego el tipo original se copiaría al nuevo, dejando ambos objetos en la memoria (hasta que los recolectores de basura eliminen uno o ambos) .
Como ejemplo, considere el siguiente código:
class baseClass {} class childClass : baseClass {} class otherClass {} public void doSomethingWithBase(baseClass item) {} public void mainMethod() { var obj1 = new baseClass(); var obj2 = new childClass(); var obj3 = new otherClass(); doSomethingWithBase(obj1); //not a problem, obj1 is already of type baseClass doSomethingWithBase(obj2); //not a problem, obj2 is implicitly casted to baseClass doSomethingWithBase(obj3); //won't compile without additional code }
baseClass
baseClass
otherClass
abaseClass
, lo que implicará crear un nuevo objeto de tipo baseClass y completarlo copiando los datos de obj3.Un buen ejemplo es la clase Convert C #, donde proporciona código personalizado para convertir entre diferentes tipos.
fuente
La fundición conserva el tipo de objetos. La coerción no lo hace.
Coerción es tomar el valor de un tipo que NO es compatible con la asignación y convertirlo a un tipo que es compatible con la asignación. Aquí realizo una coacción porque
Int32
NO hereda deInt64
... entonces NO es compatible con la asignación. Esta es una coerción cada vez mayor (no se pierden datos). Una coerción amplia es también conocida como conversión implícita . Una coacción realiza una conversión.void Main() { System.Int32 a = 100; System.Int64 b = a; b.GetType();//The type is System.Int64. }
El casting le permite tratar un tipo como si fuera de un tipo diferente mientras también conserva el tipo .
void Main() { Derived d = new Derived(); Base bb = d; //b.N();//INVALID. Calls to the type Derived are not possible because bb is of type Base bb.GetType();//The type is Derived. bb is still of type Derived despite not being able to call members of Test } class Base { public void M() {} } class Derived: Base { public void N() {} }
Fuente: Estándar anotado de Common Language Infrastructure por James S. Miller
Ahora, lo que es extraño es que la documentación de Microsoft sobre Casting no se alinea con la definición de Casting de la especificación ecma-335.
... Esto suena como coerción, no a casting.
Por ejemplo,
object o = 1; int i = (int)o;//Explicit conversions require a cast operator i.GetType();//The type has been explicitly converted to System.Int32. Object type is not preserved. This meets the definition of Coercion not casting.
¿Quién sabe? Tal vez Microsoft esté comprobando si alguien lee estas cosas.
fuente
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 #.
fuente
Desde el estándar CLI :
fuente
Según Wikipedia,
La diferencia entre la conversión de tipos y la coerción de tipos es la siguiente:
TYPE CASTING | TYPE COERCION | 1. Explicit i.e., done by user | 1. Implicit i.e., done by the compiler | 2. Types: | 2. Type: Static (done at compile time) | Widening (conversion to higher data | type) Dynamic (done at run time) | Narrowing (conversion to lower data | type) | 3. Casting never changes the | 3. Coercion can result in representation the actual type of object | as well as type change. nor representation. |
Nota : el casting no es conversión. Es solo el proceso mediante el cual tratamos un tipo de objeto como otro tipo. Por lo tanto, el tipo real de objeto, así como la representación, no cambia durante el lanzamiento.
Estoy de acuerdo con las palabras de @ PedroC88:
fuente