2012-01-13 27 views
67

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 claros acerca de la distinción.¿Cuál es la diferencia entre el colado y la coerción?

¿Existe alguna forma clara y simple de explicar la diferencia que ustedes conocen?

Conversión de tipo (también conocido a veces como tipo fundido)

Para utilizar un valor de un tipo en un contexto que espera otro.

tipo Nonconverting fundido (a veces conocido como tipo juego de palabras)

Un cambio que no altera los bits subyacentes.

Coercion

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 que rodea.

+4

¿Qué pasa con el [artículo de Wikipedia] (http://en.wikipedia.org/wiki/Type_conversion)? –

Respuesta

83

Type Conversion:

La palabra conversión refiere a cambiar de forma implícita o explícitamente un valor de un tipo de datos a otro, por ejemplo un entero de 16 bits a un entero de 32 bits.

La palabra coerción se utiliza para denotar una conversión implícita.

La palabra fundido se refiere normalmente a una conversión explícita de tipos (en contraposición a una conversión implícita), independientemente de si se trata de una reinterpretación de un patrón de bits o una conversión real.

Entonces, la coerción es implícita, el reparto es explícito y la conversión es cualquiera de ellos.


Pocos ejemplos (de la same source):

coacció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 
+0

¿Esto haría que la "coerción implícita" fuera redundante? la nota [aquí] (http://www.postgresql.org/docs/8.4/static/functions-string.html) utiliza tanto "coerción implícita" como "coerción explícita" –

+0

La conversión implícita solo se puede realizar cuando no se está perder precisión o tener sentido (Ej .: Int -> doble). En el lenguaje más moderno, no puede hacer double-> int porque perdería precisión. Con la coerción de tipo, eso no es un "problema". –

6

La conversión es el proceso por el cual se trata un tipo de objeto como otro tipo, Coercing es la conversión de un objeto a otro.

Tenga en cuenta que en el proceso anterior no hay conversión involucrados, tiene un tipo que le gustaría tratar como otra, digamos por ejemplo, usted tiene 3 diferentes objetos que heredan de un tipo base, y tiene un método que tomará ese tipo de base, en cualquier momento, si ahora tiene el tipo de hijo específico, puede ENCONTRARLO a 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á en el nuevo, dejando ambos objetos en la memoria (hasta que los recolectores de basura se lleven , o ambos).

+1

Un ejemplo ayudaría a aclarar la distinción que está tratando de hacer. –

+0

Pensé en el ejemplo y lo seguí de inmediato;) – PedroC88

1

continuación se presenta una publicando desde el following article:

A menudo se descuida la diferencia entre coerción y colada. Puedo ver porque; muchos idiomas tienen la misma sintaxis y terminología para ambas operaciones. Algunos lenguajes incluso pueden referirse a cualquier conversión como "fundició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 coacción. La coerción le permite usar el nuevo tipo al crear un nuevo valor que de alguna manera se asemeja al original. Algunas coerciones pueden descartar datos (por ejemplo, convertir el int 0x12345678 en el 0x5678 corto), mientras que otros pueden no (por ejemplo, convertir el int 0x00000008 en el 0x0008 corto, o el 0x0000000000000008 largo).

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. Casting simplemente indica que desea operar en un tipo particular que incluye un valor.

La diferencia en el nivel de código varía de C# a IL. En C#, tanto la fundición y la coacció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, hay algunas diferencias importantes. Lo que es más importante 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; coersion crea una instancia nueva y distinta, mientras que la conversión no. Un corolario es que el resultado del lanzamiento y el original siempre serán equivalentes (tanto en identidad como en igualdad), pero un valor forzado 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 su valor. Las cosas se ponen un poco más complicadas cuando trabajas 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 ejemplo siguiente, una conversión es un yeso, mientras que el otro es un coacción.

Tuple<string, string> tuple = name; 
string[] strings = name; 

Después de estas conversiones, tuplas y el nombre son iguales, pero las cadenas no es igual a ninguno de ellos. Podría hacer que la situación sea ligeramente mejor (o un poco más confusa) al implementar Equals() y operator ==() en la clase Name para comparar un Nombre y una cadena [].Estos operadores "arreglarían" el problema de comparación, pero aún tendrían dos instancias separadas; cualquier modificación de las cadenas no se reflejaría en nombre o tupla, mientras que los cambios a uno de nombre o tupla se reflejarían en nombre y tupla, pero no en cadenas.

Aunque el ejemplo de arriba intentaba ilustrar algunas diferencias entre el casting y la coerción, también sirve como un gran ejemplo de por qué debe ser extremadamente precavido al usar operadores de conversión con tipos de referencia en C#.

20

Los usos varían, como usted nota.

Mis usos personales son:

  • Un "molde" es el uso de un operador fundido. Un operador de conversión instruye al compilador que o bien (1) se sabe que esta expresión no es 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 del tipo dado, y el tiempo de ejecución producirá un error si no es así, o (2) la expresión es de un tipo diferente por completo, pero hay una forma conocida de asociar instancias del tipo de expresión con instancias del tipo de conversión. El compilador recibe instrucciones para generar código que realice la conversión. El lector atento observará que estos son opuestos, lo que creo que es un truco ingenioso.

  • 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 doble, o puede ser "representación preservada" como una cadena a un objeto. Las conversiones pueden ser "implícitas", que no requieren un lanzamiento, o "explícito", que sí requieren un lanzamiento.

  • Una "coerción" es una conversión implícita que cambia la representación.

+0

Creo que la primera frase de esta respuesta es lo más importante de todo. Los diferentes idiomas usan estos términos para significar cosas bastante diferentes. En Haskell, por ejemplo, una "coacción" * nunca * cambia de representación; una coerción segura, '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 (y hará que los demonios salgan de tu nariz si lo usas mal). – dfeuer

+0

@dfeuer punto de datos interesante, gracias! Observo que la especificación C# no define "coerción"; mi sugerencia es exactamente lo que quiero decir en lo personal. Dado que el término parece poco definido, generalmente lo evito. –

Cuestiones relacionadas