2010-07-02 34 views

Respuesta

44

creo que lo que Eric está tratando de decir es:

de fundición es un término que describe la sintaxis (de ahí el significado sintáctico ).

Conversión es un término que describe las acciones que se toman realmente detrás de las escenas (y así el significado semántico ).

A cast-expression is used to convert explicitly an expression to a given type.

Y

A cast-expression of the form (T)E, where T is a type and E is a unary-expression, performs an explicit conversion (§13.2) of the value of E to type T.

parece respaldar eso diciendo que un operador de conversión en la sintaxis realiza una conversión explícita.

+3

+1. Hasta ahora, la única respuesta que he visto parece emparejarse con lo que Eric estaba diciendo. –

+0

+1: Sucinto. (15 caracteres) – MikeD

+5

No, no creo que sea eso lo que quiso decir. La sintaxis se llama conversión, pero no siempre se realiza una conversión entre bastidores. Si realmente haces un casting, no hay conversión en curso. Puede que incluso no cree ningún código, sino que solo le dice al compilador de qué tipo debería considerarse una referencia. – Guffa

6

Sólo mi entendimiento, probablemente demasiado simple:

Cuando se lanza los datos esenciales se mantiene intacta (la misma representación interna) - "Sé que esto es un diccionario, pero se puede usar como un ICollection".

Al convertir, está cambiando la representación interna a otra cosa - "Quiero que esta int sea una cadena".

+0

Un lanzamiento de un corto a un int en C# también causa una conversión (2 bytes a 4 bytes). Solo arroja hacia arriba o hacia abajo un objeto de referencia de heiraraquía, no causa conversiones. –

+1

Lo que describes como un casting es en realidad una conversión de ampliación. http://msdn.microsoft.com/en-us/library/k1e94s7e%28VS.80%29.aspx – Guffa

+0

@Jeffrey L Whitledge, @Guffa - gracias por la corrección. Respuesta actualizada – Oded

76

Casting es una manera de decirle al compilador que "Object X es realmente Type Y, adelante y trátelo como tal".

La conversión dice "Sé que el Objeto X no es del Tipo Y, pero existe una forma de crear un Objeto nuevo a partir de X del Tipo Y, adelante, hazlo".

+6

Gran definición, pero ¿por qué entonces (int) 5.5 se llama molde en C/C++? Definitivamente es una conversión. – Andrey

+11

Me encantan las explicaciones lógicas fáciles como estas. +1 – Mike

+1

Además, ¿qué opinas sobre el error típico de compilación de C#: "No se puede convertir implícitamente el tipo 'objeto' en 'cadena'. Existe una conversión explícita (¿falta un molde?)" Parece que todo se mezcla. – Andrey

1

En este contexto, la conversión significa que está exponiendo un objeto de un tipo dado para su manipulación como otro tipo, la conversión significa que realmente está cambiando un objeto de un tipo dado a un objeto de otro tipo.

0

This page de la documentación de MSDN C# sugiere que un elenco es una instancia específica de conversión: la "conversión explícita". Es decir, una conversión del formulario x = (int)y es un elenco.

Los cambios automáticos del tipo de datos (como myLong = myInt) son la "conversión" más genérica.

+1

No, no sugiere que un yeso sea un tipo de conversión, dice que para realizar una conversión explícita, se requiere un yeso (específicamente, el uso del * operador de lanzamiento *). La conversión es * instrucción de idioma *, no * una operación * que es distinta de la conversión. –

+0

Verdadero; la página sugiere que el operador de casting es necesario para la conversión explícita, y que esto es necesario si se pierde algún dato en la conversión. Así que sí, técnicamente el casting es la operación * que realiza * un tipo de coversion, pero creo que mi respuesta está más cerca de la verdad que la actual más votada (lo que contradice la documentación por completo). ¡La respuesta de Jason Punyon recibe mi voto! –

+0

@ Adam. Te digo que Dan y tú están un tanto confundidos. La conversión es una operación que ocurre en la capa de semántica de denotación (donde los tipos se expresan en su semántica completa). Un lanzamiento puede o no (por ejemplo, upcasting) provocar una conversión en la capa semántica de tiempo de ejecución. Verá todos los votos a favor en mi respuesta indica que la mayoría de la gente no comprende las diferencias entre [semántica denotacional y semántica operacional (ejecución)] (http://en.wikipedia.org/wiki/Semantics_of_programming_languages). –

5

Después de leer los comentarios de Eric, un intento en la llanura Inglés:

casting significa que los dos tipos son en realidad la misma en algún nivel. Pueden implementar la misma interfaz o heredar de la misma clase base o el objetivo puede ser "lo suficientemente similar" (¿un superconjunto?) Para que funcione el reparto, como el lanzamiento de Int16 a Int32.

Convertir los tipos significa que los dos objetos pueden ser lo suficientemente similares para convertirse. Tome por ejemplo una representación de cadena de un número. Es una cadena, no se puede simplemente convertir en un número, necesita analizarse y convertirse de una a la otra, y el proceso puede fallar. También puede fallar el lanzamiento, pero me imagino que es una falla mucho menos costosa.

Y esa es la diferencia clave entre los dos conceptos, creo. La conversión implicará algún tipo de análisis sintáctico, o un análisis más profundo y la conversión de los datos fuente. Casting no analiza. Simplemente intenta una coincidencia a algún nivel polimórfico.

7

Desde el Spec C# 14.6.6:

A cast-expression is used to convert explicitly an expression to a given type.
...
A cast-expression of the form (T)E, where T is a type and E is a unary-expression, performs an explicit conversion (§13.2) of the value of E to type T.

Así fundición es una construcción sintáctica utilizada para indicar al compilador para invocar conversiones explícitas.

Desde el Spec C# §13:

A conversion enables an expression of one type to be treated as another type. Conversions can be implicit or explicit, and this determines whether an explicit cast is required. [Example: For instance, the conversion from type int to type long is implicit, so expressions of type int can implicitly be treated as type long. The opposite conversion, from type long to type int, is explicit, so an explicit cast is required.

lo que las conversiones son donde el trabajo real se hace. Observará que la cita de expresión de conversión indica que realiza conversiones explícitas, pero las conversiones explícitas son un superconjunto de conversiones implícitas, por lo que también puede invocar conversiones implícitas (aunque no sea necesario) a través de expresiones de conversión.

+0

... entre otras cosas. La sintaxis de conversión también se puede usar para indicar al compilador que realice un lanzamiento. – Guffa

+0

@Guffa: ¿Tiene una referencia para eso? Solo hay 5 instancias de la palabra "fundición" en el cuerpo de la especificación C# y ninguna de esas instancias define nada ... –

2

Casting es la creación de un valor de un tipo a partir de otro valor de otro tipo. La conversión es un tipo de fundición en el que también se debe cambiar la representación interna del valor (en lugar de solo su interpretación).

En C#, fundición y conversión están ambos hechos con un reparto-expresión :

(tipo) unario-expresión

La distinción es importante (y el punto se hace en el comentario) porque solo las conversiones pueden crearse mediante un conversion-operator-declarator. Por lo tanto, solo se pueden crear conversiones (implícitas o explícitas) en el código.

Existe una conversión implícita sin conversión para las conversiones de subtipo a supertipo, y una conversión explícita sin conversión siempre está disponible para conversiones de subtipo a subtipo. No se permiten otros lanzamientos sin conversión.

0

Un elenco es un operador en una clase/estructura. Una conversión es un método/proceso en una o la otra de las clases afectadas/estructuras, o puede estar en una completa diferente clase/struct (es decir Converter.ToInt32()

operadores de conversión son de dos tipos: implícitos y explícitos

operadores de conversión implícitas indican que los datos de un tipo (por ejemplo, Int32) pueden siempre ser representados como otro tipo (decimal) sin pérdida de datos/ precisión.

int i = 25; 
decimal d = i; 

operadores de conversión explícita indican t Los datos de sombrero de un tipo (decimal) pueden siempre ser fielmente representados como otro tipo (int), pero puede haber pérdida de datos/precisión.Para ello el compilador requiere que explícitamente estado que usted es consciente de esto y quiere hacerlo de todos modos, a través del uso de la sintaxis de conversión explícita:

decimal d = 25.0001; 
int i = (int)d; 

conversión tiene dos tipos que no están necesariamente relacionados de alguna manera , e intenta convertir uno en el otro a través de algún proceso, como el análisis sintáctico. Si todos los algoritmos de conversión conocidos fallan, el proceso puede o bien lanzar una excepción o devolver un valor predeterminado:

string s = "200"; 
int i = Converter.ToInt32(s); // set i to 200 by parsing s 

string s = "two hundred"; 
int i = Converter.ToInt32(s); // sets i to 0 because the parse fails 

referencias de Eric para la conversión sintáctica frente a la conversión Symantic son básicamente un operador vs distinción metodología.

0

Un yeso es sintáctico y puede o no implicar una conversión (dependiendo del tipo de molde). Como sabe, C++ permite especificar the type of cast que desea utilizar.

casting arriba/abajo en la jerarquía puede o no puede ser considerado conversión, dependiendo de a quién le pregunte (y en qué idioma que están hablando!)

Eric (C#) está diciendo que la fundición a una el tipo diferente siempre implica una conversión, aunque esa conversión puede incluso no cambiar la representación interna de la instancia.

A C++ - chico va a estar en desacuerdo, ya que un static_cast podría no dar lugar a ningún código adicional (por lo que la "conversión" no es en realidad de verdad!)

0

Fundición y conversión son básicamente el mismo concepto en C#, excepto que una conversión se puede hacer usando cualquier método como Object.ToString(). La conversión solo se realiza con el operador de conversión (T) E, que se describe en otras publicaciones, y puede hacer uso de conversiones o boxeo.

¿Qué método de conversión usa? El compilador decide basándose en las clases y bibliotecas proporcionadas al compilador en tiempo de compilación. Si existe una conversión implícita, no es necesario que utilice el operador de conversión. Object o = String.Empty. Si solo existen conversiones explícitas, debe usar el operador de conversión. String s = (String) o.

Puede createexplicit y implicit operadores de conversión en sus propias clases. Nota: las conversiones pueden hacer que los datos se vean muy similares o que no se parezcan al tipo original para usted y para mí, pero todo está definido por los métodos de conversión y lo hace legal para el compilador.

Fundición siempre se refiere al uso del operador de fundición. Puede escribir

Object o = float.NaN; 
String s = (String) o; 

Pero si accede a s, por ejemplo, en un Console.WriteLine, recibirá un tiempo de ejecución InvalidCastException. Por lo tanto, el operador de transmisión aún intenta utilizar la conversión en el momento del acceso, pero se conformará con el boxeo durante la asignación.

42

Me recuerda la anécdota contada por Richard Feynman en la que está asistiendo a una clase de filosofía y el profesor le pregunta: "¿Feynman, eres físico, en tu opinión es un electrón y un 'objeto esencial'?" Entonces Feynman pregunta la pregunta aclaratoria "¿es un ladrillo un objeto esencial?" a la clase. Cada estudiante tiene una respuesta diferente a esa pregunta. Dicen que la noción fundamental y abstracta de "brickness" es el objeto esencial. No, un ladrillo específico y único es el objeto esencial. No, las partes del ladrillo que puedes observar empíricamente son el objeto esencial.Y así.

Cuál es por supuesto no contestar su pregunta.

No voy a revisar todas estas docenas de respuestas y debatir con sus autores sobre lo que realmente quise decir. Escribiré un artículo de blog sobre el tema en unas semanas y veremos si eso arroja alguna luz sobre el asunto.

Qué tal una analogía, a la Feynman. Deseas hornear un pan de plátano el sábado por la mañana (como hago casi todos los sábados por la mañana). Así que consulta The Joy of Cooking, y dice "bla, bla, bla ... En otro cuenco, mezcle los ingredientes secos. .."

evidente que hay una fuerte relación entre la instrucción y que sus acciones mañana por la mañana, pero igualmente claro que sería un error confundir la instrucción con la acción . La instrucción consiste en texto. Tiene una ubicación, en una página en particular. Tiene puntuación Si estuvieras en la cocina juntando harina y bicarbonato de sodio, y alguien preguntara "¿cuál es tu puntuación en este momento?", Probablemente pensarías que era una pregunta extraña. La acción está relacionada con la instrucción, pero las propiedades textuales de la instrucción no son propiedades de la acción.

Un lanzamiento no es una conversión de la misma manera que una receta no es el acto de hornear un pastel. Una receta es un texto que describe una acción, que luego puede realizar. Un operador de transmisión es texto que describe una acción, una conversión, que el tiempo de ejecución puede realizar.

+0

No hay duda si C# está en buenas manos. –

+7

Parte de mí se pregunta cómo es trabajar con Eric. La otra parte espera que no haya anulado demasiado su significado en mi publicación. –

+0

O dicho de manera más simple, un lanzamiento puede ser borrado en tiempo de compilación; mientras que, una conversión requiere alguna acción en tiempo de ejecución. Por ejemplo, a veces es necesario un elenco para decirle al compilador qué tipo desea inferir, para los idiomas que sí lo hacen. –

-6

INSERTADO editar # 2: no es la miopía hilarante inconsistentes que desde que he proporcionado esta respuesta, la cuestión se ha marcado como duplicado de una cuestión que se pregunta, "está lanzando lo mismo que la conversión?". Y las respuestas de "No" son abrumadoramente subidas. Sin embargo, mi respuesta aquí que señala la esencia generadora de por qué los moldes no son lo mismo que la conversión es abrumadoramente downvoted (pero tengo uno +1 en los comentarios). Supongo que los lectores tienen dificultades para comprender que los moldes se aplican en la capa de sintaxis/semántica denotacional y las conversiones se aplican en la capa de semántica operacional. Por ejemplo, un molde de una referencia (o puntero en C/C++) - refiriéndose a un tipo de datos encuadrado - a otro tipo de datos, no genera (en todos los idiomas y escenarios) una conversión de los datos encuadrados. Por ejemplo, en C float a[1]; int* p = (int*)&a; no se asegura de que *p se refiera a datos int.

Un compilador compila desde denotational semántica hasta operational semantics. La compilación no es biyectiva, es decir, no se garantiza que no se compile (por ejemplo, Java, LLVM, asm.js o C# bytecode) a ninguna sintaxis denotacional que se compile con ese bytecode (por ejemplo, Scala, Python, C#, C mediante Emscripten, etc.) Por lo tanto, las dos capas no son lo mismo.

Así, la mayoría, obviamente, un ' fundido' y una 'conversión ' no son la misma cosa. Mi respuesta aquí es señalar que los términos se aplican a dos capas diferentes de semántica. Los lanzamientos se aplican a la semántica de lo que conoce la capa de denotación (sintaxis de entrada del compilador). Las conversiones se aplican a la semántica de lo que conoce la capa operativa (tiempo de ejecución o byte intermedio). Usé el término estándar de 'borrado' para describir lo que sucede con la semántica de denotación que no se registra explícitamente en la capa de semántica operacional.

Por ejemplo, los genéricos reificados son un ejemplo de grabación semántica de denotación en la capa de semántica operacional, pero tienen la desventaja de hacer que la capa de semántica operacional sea incompatible con la semántica de denotación de orden superior, p. por eso fue doloroso considerar implementar los genéricos de mayor nivel de Scala en CLR de C# porque la semántica denotacional de C# para genéricos estaba codificada de forma rígida en la capa de semántica operacional.

Vamos muchachos, dejen de votar a alguien que sabe mucho más que usted. Haga su tarea primero antes de votar.


INSERTADA EDIT: Casting es una operación que ocurre en la capa semántica denotational (donde tipos se expresan en sus plenos semántica). Un molde puede (por ejemplo, una conversión explícita) o no (por ejemplo, una conversión ascendente) provocar una conversión en la capa semántica de tiempo de ejecución. Los votos negativos sobre mi respuesta (y la votación ascendente sobre el comentario de Marc Gavin) me indican que la mayoría de las personas no entienden las diferencias entre denotational semantics and operational (execution) semantics. Suspiro.


voy a indicar la respuesta de Eric Lippert más simple y más en general para todos los idiomas, incluyendo C# .

A fundido es sintaxis de modo (como todos sintaxis) es borrado en tiempo de compilación; mientras que, una conversión causa un poco de acción en el tiempo de ejecución.


Esa es una afirmación verdadera para cada lenguaje de computadora que conozco en todo el universo. Tenga en cuenta que la declaración anterior no dice que fundición y conversiones son mutuamente excluyentes.

Un fundido puede causar una conversión en tiempo de ejecución, pero hay casos en los que no.

La razón por la que tenemos dos palabras distintas, es decir fundido y conversión, es que necesitamos una manera de describir por separado lo que está sucediendo en sintaxis (el operador de conversión) y al tiempo de ejecución (conversión o verificación de tipo y posible conversión).

Es importante que mantengamos esta separación de conceptos, porque en algunos lenguajes de programación el molde nunca causa una conversión. Además, para que comprendamos la conversión implícita (por ejemplo, upcasting) solo ocurre en tiempo de compilación. La razón por la que escribí esta respuesta es porque quiero ayudar a los lectores a entender en términos de ser multilingüe con los lenguajes de computadora. Y también para ver cómo esa definición general también se aplica correctamente en el caso de C#.

También quería ayudar a los lectores a ver cómo generalizo los conceptos en mi mente, lo cual me ayuda como diseñador de lenguaje de computadora. Estoy tratando de transmitir el don de una forma de pensar muy reduccionista y abstracta. Pero también estoy tratando de explicar esto de una manera muy práctica. Por favor, no dude en dejarme saber en los comentarios si necesito mejorar la elucidación.


Eric Lippert escribió:

A cast is not a conversion in the same way that a recipe is not the act of baking a cake. A recipe is text which describes an action, which you can then perform. A cast operator is text which describes an action - a conversion - which the runtime can then perform.

La receta es lo que está sucediendo en la sintaxis. La sintaxis siempre se borra, y se reemplaza con nada o algún código de tiempo de ejecución.

Por ejemplo, puedo escribir un elenco en C# que no hace nada y se borra por completo en tiempo de compilación cuando es does not cause a change in the storage requirements o es upcasting. Podemos ver claramente que un elenco es solo una sintaxis, que no cambia el código de tiempo de ejecución.

int x = 1; 
int y = (int)x; 
Giraffe g = new Giraffe(); 
Animal a = (Animal)g; 

que se pueden utilizar para fines de documentación (todavía ruidosa), pero es esencial en idiomas que tienen inferencia de tipos, donde un elenco a veces es necesario indicar al compilador qué tipo usted lo desea para inferir.

Para an example, en Scala un None tiene el tipo de Option[Nothing] donde Nothing es el tipo de fondo que es la sub de tipo de todos los tipos posibles (no súper de tipo). Por lo tanto, a veces, cuando se utiliza None, el tipo debe enviarse a un tipo específico, porque Scala only does local type inference, por lo tanto, no siempre puede inferir el tipo que pretendía.

// (None : Option[Int]) casts None to Option[Int] 
println(Some(7) <*> ((None : Option[Int]) <*> (Some(9) > add))) 

Un molde podría saber en tiempo de compilación que requiere una conversión de tipo, por ejemplo, int x = (int)1.5, o podría requerir una verificación de tipo y posible conversión de tipo en tiempo de ejecución, p. downcasting. El molde (es decir, la sintaxis) se borra y se reemplaza con la acción de tiempo de ejecución.

Por lo tanto, podemos ver claramente que equiparar todos los moldes con la conversión explícita, es un error de implicación en el MSDN documentation. Esa documentación tiene la intención de decir que la conversión explícita requiere un operador de conversión , pero no debe estar tratando de implicar que todas las conversiones son conversiones explícitas. Estoy seguro de que Eric Lippert puede aclarar esto cuando escribe el blog que prometió en su respuesta.


AÑADIR: A partir de los comentarios y charlar, puedo ver que hay cierta confusión sobre el significado del término borrado.

El término 'borrado' se utiliza para describir información conocida en tiempo de compilación, que no se conoce en tiempo de ejecución. Por ejemplo, los tipos pueden borrarse en genéricos no reificados, y se llama type erasure.

En general, toda la sintaxis se borra, porque generalmente CLI no es biyectiva (invertible y uno a uno) con C#. No siempre puede retroceder desde un código CLI arbitrario al código fuente exacto de C#. Esto significa que la información ha sido borrada.

Los que dicen borraron no es el término correcto, están combinando la implementación de un elenco con la semántica del elenco. El elenco es una semántica de nivel superior (creo que en realidad es más alta que sintaxis, es una semántica denotacional al menos en caso de subidas y bajadas) que dice en ese nivel de semántica que queremos lanzar el tipo.Ahora, cómo se hace eso en el tiempo de ejecución es un nivel de semántica completamente diferente. En algunos idiomas, puede ser siempre NOOP. Por ejemplo, en Haskell toda la información de tipeo se borra en tiempo de compilación.

+6

No creo que esto realmente esté confirmando la respuesta de Eric. Afirmar que un elenco se "borró en tiempo de compilación" sugiere que no tiene ningún significado. * Algunas veces * eso será cierto (a veces el elenco no requerirá ninguna acción) pero generalmente no es verdadero (requiere que el compilador emita IL para ejecutar la conversión en el momento de la ejecución). Si va a hablar incluso de un elenco que requiera que se "borre" la conversión, el término carece de sentido, ya que * todo * el código fuente es presumiblemente "borrado" por el compilador. Creo que el uso del término "borrar" hace más para confundir que para ilustrar aquí. –

+3

(Creo que sería más claro decir que un molde puede o no * ser traducido * por el compilador en código que causará una conversión en tiempo de ejecución). –

+4

El ejemplo 'Animal' /' Jirafa' es malo ; ahora imagine: 'Animal a = new Dog(); Jirafa g = (Jirafa) a; 'Definitivamente es ** no ** borrado en el momento de la compilación, y no es una conversión (nada se cambia, nada se convierte, esta es una operación que preserva la referencia) - una 'clase de castillos' se produce código de operación, que es una operación de ** tiempo de ejecución ** para hacer una verificación de tipo.Si bien el compilador ** puede eliminar algunas veces ** (si siempre es claro), eso no significa que ** siempre ** se elimine, por lo que no es correcto decir que un "elenco ** ** se borró en tiempo de compilación "(énfasis mío). –

Cuestiones relacionadas