2009-10-01 9 views
31

Tengo una pregunta acerca de la conversión de tipo implícitaCopia tipo implícita en C#

¿Por qué esta conversión de tipo implícito funciona en C#? Aprendí que el código implícito generalmente no funciona.

Tengo un ejemplo de código aquí acerca de la conversión de tipos implícita

char c = 'a'; 
int x = c; 
int n = 5; 
int answer = n * c; 
Console.WriteLine(answer); 
+0

Esa es una muy buena pregunta. En C, un personaje es más o menos un sinónimo de un byte, ambos son tipos numéricos. Sin embargo, en C#, un personaje es un carácter unicode ... –

+0

, entonces la respuesta sería porque el personaje es un carácter unicode por eso funciona en C#? – tintincutes

+20

Solo para corregir el uso de la jerga, este no es un elenco implícito. Esta es una conversión implícita. "Casting" es el uso del operador de reparto; una conversión implícita es una conversión que NO requiere el operador de conversión. –

Respuesta

2

La fundición causará la pérdida de datos. Aquí char es de 16 bits y int es de 32 bits. Entonces el reparto sucederá sin pérdida de datos.

Ejemplo de vida real: podemos poner un pequeño recipiente en un recipiente grande pero no al revés sin ayuda externa.

0

Funciona porque cada personaje se maneja internamente como un número, por lo tanto, el elenco está implícito.

+2

Aunque plausible, este razonamiento no es realmente lógico. Si ese fuera el razonamiento, entonces habría una conversión implícita de ushort a char, pero no hay tal conversión implícita. –

12

La idea básica es que las conversiones que conducen a posibles pérdidas de datos pueden ser implícitas, mientras que las conversiones que pueden conducir a la pérdida de datos deben ser explícitas (utilizando, por ejemplo, un operador de conversión).

Convertir implícitamente de char a int funcionará en C#.

[Editar] Como otros señalaron, un char es un número de 16 bits en C#, por lo que esta conversión es solo de un entero de 16 bits a un entero de 32 bits, que es posible sin pérdida de datos./edit]

C# admite conversiones implícitas, la parte "normalmente no funciona" probablemente provenga de algún otro lenguaje, probablemente C++, donde algunas implementaciones gloriosas string proporcionaron conversiones implícitas a diversos tipos de punteros, creando algunos errores gigantescos en aplicaciones.

Cuando, en cualquier idioma, proporciona conversiones de tipo, también debe realizar conversiones explícitas por defecto y solo proporcionar conversiones implícitas para casos especiales.

+3

Entonces, ¿qué explica por qué en C# no hay conversión implícita de corto a char? Eso se puede hacer sin pérdidas; su lógica indicaría que debería haber una conversión implícita de corto a char, pero no es así. Por qué no? –

+0

Es por eso que dije "idea básica", como lo obtuve del libro "CLR vía C#". La última palabra se dice en la referencia, citada por _Dzmitry Huba_. No conozco los motivos de esta decisión, pero espero que hayan intentado mejorar un poco la diferencia semántica entre los caracteres y los números, similar a tener que marcar los parámetros 'ref' y' out' en el sitio de llamadas. – gimpf

+0

De hecho. Como resultado, sé un poco sobre la razón de esta decisión.Tu conjetura es perfecta. :) –

0

El char se envía implícitamente a su valor numérico Unicode, que es un número entero.

+2

El tipo 'char' representa caracteres Unicode. Solo 128 de los 65.536 posibles valores 'char' tienen un equivalente ASCII. – LukeH

+0

Tienes razón, no estoy seguro de lo que estaba pensando ... editado. –

9

De C# Especificación

6.1.2 conversiones numéricas implícitas Las conversiones numéricas implícitas son:

• De sbyte a corto, int, long, float, double o decimal.

• A partir de bytes a corto, ushort, int, uint , largo, ulong, float, double o decimal.

• De corto a int, largo, flotante, doble o decimal.

• De ushort a int, uint, long, ulong, float, double o decimal.

• De int a largo, flotante, doble o decimal.

• Desde uint a long, ulong, float, double o decimal.

• De largo a flotante, doble o decimal.

• De ulong a flotante, doble o decimal.

• Desde char a ushort, int, uint, largo, ulong, flotante, doble o decimal.

• De flotación a doble.

Las conversiones de int, uint largo, o ulong a flotar y de largo o ULONG duplicar puede causar una pérdida de precisión, pero nunca causarán una pérdida de magnitud. Las otras conversiones numéricas implícitas nunca pierden ninguna información . No hay conversiones implícitas al tipo de caracteres, por lo que valores de los otros tipos integrales do no se convierten automáticamente al tipo char.

3

Desde la página de MSDN sobre el carbón de leña (char (C# Reference):.

un char puede ser implícita convierte en ushort, int, uint larga, ulong, flotador, doble o decimal Sin embargo, hay no hay conversiones implícitas de otros tipos al tipo char.

es porque se han puesto en marcha un implicit method de char a todos esos tipos. Ahora bien, si usted pregunta por qué se les aplican, realmente no estoy seguro, sin duda para ayudar trabajando con la representación ASCII de caracteres o algo así.

+0

sí, es por eso que también me pregunté, soy nuevo en la programación, pero como mi profesor lo explica, vi la inconsistencia de la misma. Especialmente en C#, son muy estrictas con las reglas de OO y deben estar limpias todo el tiempo, y esta es bastante sorprendente. – tintincutes

+0

'char' no * explícitamente * implementa "conversión implícita". Si miras la fuente Char con reflector, no puedes ver ninguno de estos. Algunas ** conversiones ** están implícitas para el idioma en sí. –

70

ACTUALIZACIÓN: Estoy usando esta pregunta como tema de mi blog hoy. Gracias por la gran pregunta. Por favor, vea el blog para futuras adiciones, actualizaciones, comentarios, etc.

http://blogs.msdn.com/ericlippert/archive/2009/10/01/why-does-char-convert-implicitly-to-ushort-but-not-vice-versa.aspx


No está del todo claro para mí qué es exactamente lo que está pidiendo. Las preguntas "por qué" son difíciles de responder. Pero voy a intentarlo.

Primero, código que tiene una conversión implícita de char a int (nota: esto no es un "molde implícito", esto es una "conversión implícita") es legal porque la especificación C# establece claramente que hay una conversión implícita de char a int, y el compilador es, a este respecto, una implementación correcta de la especificación.

Ahora, puede señalar sensiblemente que la pregunta se ha rogado por completo. ¿Por qué hay una conversión implícita de char a int? ¿Por qué los diseñadores del lenguaje creen que esta es una regla sensata para agregar al lenguaje?

Bueno, antes que nada, las cosas obvias que previenen que sean una norma del lenguaje no se aplican. Un char se implementa como un entero de 16 bits sin signo que representa un carácter en una codificación UTF-16, por lo que se puede convertir a un ushort sin pérdida de precisión o, para el caso, sin cambio de representación. El tiempo de ejecución simplemente pasa de tratar este patrón de bits como un char a tratar el mismo patrón de bits como un ushort.

Es por lo tanto posible para permitir una conversión de char a ushort. Ahora, solo porque algo sea posible no significa que sea una buena idea. Claramente, los diseñadores del lenguaje pensaron que convertir implícitamente char a ushort era una buena idea, pero convertir implícitamente ushort a char no lo es. (Y como char para ushort es una buena idea, parece razonable que char-to-anything-that-ushort-goes-to también sea razonable, por lo tanto, char to int. Además, espero que esté claro por qué se permite explícitamente fundición de ushort a char es sensible, su pregunta es acerca de las conversiones implícitas)

Así que en realidad tienen dos preguntas relacionadas aquí: en primer lugar, ¿por qué es una mala idea permitir que las conversiones implícitas de ushort/corto/bytes/sbyte. ¿char? y segundo, ¿por qué es una buena idea permitir conversiones implícitas de char a ushort?

A diferencia de usted, tengo las notas originales del equipo de diseño de idiomas a mi disposición. A través de ellos, descubrimos algunos hechos interesantes.

La primera pregunta se trata en las notas del 14 de abril de 1999, donde surge la cuestión de si debería ser legal convertir de byte a char. En la versión original previa a la publicación de C#, esto fue legal por un breve tiempo. He editado ligeramente las notas para que sean claras sin una comprensión de los nombres en código de Microsoft previos a la versión de 1999. También he añadido énfasis en los puntos importantes:

[El comité de diseño de lenguajes] ha elegido para proporcionar una conversión implícita de bytes a caracteres, ya que el dominio de uno es completamente contenida por el otro. En este momento, sin embargo, [la biblioteca de ejecución ] sólo proporcionan métodos de escritura que tienen caracteres y enteros, lo que significa que los bytes copia impresa como caracteres ya que termina siendo el mejor método . Podemos resolver esto ya sea por proporcionando más métodos en la clase Writer o eliminando la conversión implícita .

Existe un argumento para explicar por qué el último es lo correcto. Después de todo, bytes realmente no son caracteres. Es verdad que puede ser un mapeo útil de bytes a caracteres, pero en última instancia, 23 no denota la mismo que el personaje con ascii valor de 23, de la misma manera que 23B denota lo mismo que 23L. Pidiendo [los autores de la biblioteca] para proporcionar este método adicional simplemente porque cómo funciona una peculiaridad en nuestro sistema de tipo parece bastante débil. Entonces, me gustaría sugieren que hagamos la conversión explícita de byte a char.

Las notas concluyen con la decisión de que byte-to-char debe ser una conversión explícita, y entero-literal-in-range-of-char también debe ser una conversión explícita.

Tenga en cuenta que las notas de diseño de idioma no indican por qué ushort-to-char también se volvió ilegal al mismo tiempo, pero puede ver que se aplica la misma lógica.Cuando se llama a un método sobrecargado como M (int) y M (char), cuando le pasa un ushort, es bueno que quiera tratar el ushort como un número, no como un personaje. Y un ushort no es una representación de caracteres de la misma manera que un ushort es una representación numérica, por lo que parece razonable hacer que esa conversión también sea ilegal.

La decisión de hacer que el carbón vaya a ushort se hizo el 17 de septiembre de 1999; las notas de diseño de ese día sobre este tema simplemente afirman "char to ushort también es una conversión legal implícita", y eso es todo. Ninguna otra exposición de lo que estaba sucediendo en las cabezas del diseñador del lenguaje ese día es evidente en las notas.

Sin embargo, podemos hacer conjeturas informadas sobre por qué implicit char-to-ushort se consideró una buena idea. La idea clave aquí es que la conversión de número a personaje es una conversión "posiblemente dudosa". Es tomar algo que NO SABES tiene la intención de ser un personaje y elegir tratarlo como tal. Parece el tipo de cosa que desea llamar que está haciendo explícitamente, en lugar de permitirlo accidentalmente. Pero el reverso es mucho menos fiable. Existe una larga tradición en la programación C de tratar caracteres como enteros: para obtener sus valores subyacentes o para hacer matemáticas sobre ellos.

En resumen: parece razonable que usar un número como personaje podría ser un accidente y un error, pero también parece razonable que el uso de un personaje como número sea deliberado y deseable. Esta asimetría se refleja, por lo tanto, en las reglas del lenguaje.

¿Eso responde su pregunta?

+0

+ ¿Cuál es el símbolo del infinito? También fue una excelente publicación de blog. – Kredns

+0

Todavía estaría bien (a veces) si esto funcionó de la caja en C# sin embargo, como lo hace en C: para (letra char = 'A'; letra <= 'Z'; letra + = 2) –

+1

Para el registro, lo anterior funciona en C#, con un poco más de sintaxis: letter = (char) (letter + 2) –

0

La conversión implícita de tipo char a número no tiene sentido, en mi opinión, porque ocurre una pérdida de información. Puede verlo en este ejemplo:

string ab = "ab"; 
char a = ab[0]; 
char b = ab[1]; 
var d = a + b; //195 

Hemos puesto toda la información de la cadena en caracteres. Si por casualidad solo se conserva la información de d, todo lo que nos queda es un número que no tiene sentido en este contexto y no puede utilizarse para recuperar la información proporcionada previamente. Por lo tanto, la forma más útil de ir sería convertir implícitamente la "suma" de caracteres en una cadena.

Cuestiones relacionadas