PROGRAMACION III – LABORATORIO III Conversiones de tipos en C# Dado que a C# se le asignan tipos estáticos en tiempo de compilación, después de declarar una variable, no se puede volver a declarar ni tampoco utilizar para almacenar valores de otro tipo, a menos que dicho tipo pueda convertirse en el tipo de la variable. Por ejemplo, no existe conversión de un entero a una cadena arbitraria cualquiera. Por lo tanto, después de declarar i como entero, no puede asignarle la cadena "Hello", como se muestra en el código siguiente. int i; i = "Hello"; // Error: "Cannot implicitly convert type 'string' to 'int'" Sin embargo, en ocasiones puede que sea necesario copiar un valor en un parámetro de método o variable de otro tipo. Por ejemplo, puede que tenga una variable de tipo entero que deba pasar a un método cuyo parámetro es de tipo double. Estos tipos de operaciones se denominan conversiones de tipos. En C#, puede realizar los siguientes tipos de conversiones: Conversiones implícitas: no se requiere una sintaxis especial porque la conversión se realiza con seguridad de tipos y no se perderán datos. Entre los ejemplos se incluyen las conversiones de tipos enteros de menor a mayor y las conversiones de clases derivadas en clases base. Conversiones explícitas (conversiones de tipos): las conversiones explícitas requieren un operador de conversión. Las variables de origen y destino son compatibles, pero existe el riesgo de perder datos debido a que el tipo de la variable de destino es más pequeño que (o es una clase base de) la variable de origen. Conversiones definidas por el usuario: las conversiones definidas por el usuario se realizan a través de métodos especiales que puede definir para habilitar las conversiones explícitas e implícitas entre tipos personalizados que no tienen una relación de clase base-clase derivada. Para obtener más información, vea Operadores de conversión (Guía de programación de C#). Conversiones con clases auxiliares: para realizar conversiones entre tipos no compatibles, como los enteros y los objetos System..::.DateTime, o bien cadenas hexadecimales y matrices de bytes, puede utilizar la clase System..::.BitConverter, la clase System..::.Convert y los métodos Parse de los tipos numéricos integrados, como Int32..::.Parse.. Conversiones implícitas En los tipos numéricos integrados, puede realizarse una conversión implícita cuando el valor que se va a almacenar puede ajustarse a la variable sin necesidad de truncamiento o redondeo. Por ejemplo, una variable de tipo longlong (Referencia de C#) (entero de 8 bytes) puede almacenar cualquier valor que pueda almacenar a su vez un elemento intint (Referencia de C#) (4 bytes en un equipo de 32 bits). En el ejemplo siguiente, el compilador convierte implícitamente el valor de la derecha en un tipo long antes de asignarlo a bigNum. // Implicit conversion. num long can // hold any value an int can hold, and more! int num = 2147483647; long bigNum = num; Tabla de conversiones numéricas implícitas La tabla siguiente muestra las conversiones numéricas implícitas predefinidas. Las conversiones implícitas se pueden dar en muchas ocasiones, incluidas la invocación a métodos y las instrucciones de asignación. De A PROGRAMACION III – LABORATORIO III sbyte short, int, long, float, double o decimal byte short, ushort, int, uint, long, ulong, float, double o decimal short int, long, float, double o decimal ushort int, uint, long, ulong, float, double o decimal int long, float, double o decimal uint long, ulong, float, double o decimal long float, double o decimal char ushort, int, uint, long, ulong, float, double o decimal float double ulong float, double o decimal Comentarios Las conversiones de int, uint o long a float y de long a double pueden causar una pérdida de precisión, pero no una pérdida de magnitud. No existen conversiones implícitas al tipo char. No hay ninguna conversión implícita entre los tipos de punto flotante y el tipo decimal. Una expresión constante de tipo int se puede convertir a sbyte, byte, short, ushort, uint o ulong, siempre que el valor de la expresión constante quede dentro del intervalo del tipo de destino. Conversiones explícitas Sin embargo, si no se puede realizar una conversión sin riesgo de perder información, el compilador requiere que se realice una conversión explícita, denominada conversión de tipo. Una conversión de tipo es una manera de informar al compilador de forma explícita de que pretende realizar la conversión y que está al tanto de que puede producirse una pérdida de datos. Para realizar una conversión de tipo, especifique entre paréntesis el tipo al que se va a aplicar dicha conversión delante del valor o la variable que se va a convertir. El programa no se compilará sin el operador de conversión de tipo. class Test { static void Main() { double x = 1234.7; int a; // Cast double to int. a = (int)x; PROGRAMACION III – LABORATORIO III System.Console.WriteLine(a); } } // Output: 1234 Tabla de conversiones numéricas explícitas (Referencia de C#) Las conversiones numéricas explícitas se utilizan para convertir cualquier tipo numérico a cualquier otro tipo numérico, para el que no existe conversión implícita, mediante una expresión que utilice el operador de conversión explícita. La siguiente tabla muestra estas conversiones. De Para sbyte byte, ushort, uint, ulong o char byte Sbyte o char short sbyte, byte, ushort, uint, ulong o char ushort sbyte, byte, short o char int sbyte, byte, short, ushort, uint, ulongo char uint sbyte, byte, short, ushort, int o char long sbyte, byte, short, ushort, int, uint, ulong o char ulong sbyte, byte, short, ushort, int, uint, long o char char sbyte, byte o short float sbyte, byte, short, ushort, int, uint, long, ulong, charo decimal double sbyte, byte, short, ushort, int, uint, long, ulong, char, floato decimal decimal sbyte, byte, short, ushort, int, uint, long, ulong, char, float o double Comentarios Las conversiones numéricas explícitas pueden producir pérdida de precisión o provocar excepciones. Cuando se convierte un valor decimal en un tipo integral, este valor se redondea hacia cero al valor entero más próximo. Si el valor entero resultante queda fuera del intervalo del tipo de destino, se produce una excepción OverflowException. Cuando se convierte un valor double o float en un tipo integral, el valor se trunca. Si el valor entero resultante queda fuera del intervalo del valor de destino, el resultado depende del contexto de comprobación de PROGRAMACION III – LABORATORIO III desbordamiento. En un contexto comprobado, se produce una excepción OverflowException, mientras que en un contexto no comprobado, el resultado es un valor no especificado del tipo de destino. Cuando se convierte double en float, el valor double se redondea al valor float más próximo. Si el valor de tipo double es demasiado pequeño o demasiado grande para ajustarse al tipo de destino, el resultado será cero o infinito. Cuando se convierte float o double en decimal, el valor de origen se convierte en una representación decimal y se redondea al número más próximo después de la vigésimo octava posición decimal si es necesario. Según el valor de origen, se puede producir uno de los siguientes resultados: Si el valor de origen es demasiado pequeño para representarlo como decimal, el resultado se convierte en cero. Si el valor de origen es NaN (no es un número), infinito o demasiado grande para ser representado como decimal, se produce una excepción OverflowException. Cuando se convierte decimal en float o double, el valor decimal se redondea al valor double o float más próximo. LITERALES ENTEROS El tipo de un literal entero se determina como sigue: Si el literal no tiene sufijo, su tipo es el primero de los tipos en los cuales se puede representar su valor: int, uint, long, ulong. Si el literal tiene el sufijo U o u, su tipo es el primero de los tipos en los cuales se puede representar su valor: uint, ulong. Si el literal tiene el sufijo L o l, su tipo es el primero de los tipos en los cuales se puede representar su valor: long, ulong. Si el literal tiene el sufijo UL, Ul, uL, ul, LU, Lu, lU o lu, es de tipo ulong. REALES Si no se especifica el sufijo de tipo real, el tipo del literal real es double. De lo contrario, el sufijo de tipo real determina el tipo del literal real, como sigue: Un literal real con el sufijo F o f es de tipo float. Por ejemplo, los literales 1f, 1.5f, 1e10f y 123.456F son de tipo float. Un literal real con el sufijo D o d es de tipo double. Por ejemplo, los literales 1d, 1.5d, 1e10d y 123.456D son de tipo double. Un literal real con el sufijo M o m es de tipo decimal. Por ejemplo, los literales 1m, 1.5m, 1e10m y 123.456M son de tipo decimal. Este literal se convierte en un valor decimal tomando el valor exacto y, si es necesario, redondeando al valor más cercano que se pueda representar mediante el redondeo de banca (Sección 4.1.7). Cualquier escala que se detecte en el literal se conserva, salvo que el valor esté redondeado o sea cero (en este caso, el signo y la escala son 0). Por lo tanto, el análisis del literal 2.900m forma un decimal con signo 0, coeficiente 2900 y escala 3. Si el literal especificado no puede representarse en el tipo indicado, se produce un error en tiempo de compilación. El valor de un literal real de tipo float o double se determina mediante el uso del modo "redondeo al más cercano" de IEEE. Tenga en cuenta que, en un literal real, siempre son necesarios dígitos decimales tras el punto decimal. Por ejemplo, 1.3F es un literal real, pero no así 1.F. Convert (Clase) Convierte un tipo de datos base en otro tipo de datos base. PROGRAMACION III – LABORATORIO III Espacio de nombres: System Comentarios Esta clase devuelve un tipo cuyo valor es equivalente al valor de un tipo especificado. Los tipos base que se admiten son Boolean, Char, SByte, Byte, Int16, Int32, Int64, UInt16, UInt32, UInt64, Single, Double, Decimal, DateTime y String. Existe un método de conversión para convertir todos y cada uno de los tipos base en los demás tipos base. Sin embargo, la llamada real a un método de conversión determinado puede generar uno de cuatro resultados, dependiendo del valor del tipo base en tiempo de ejecución y el tipo base de destino. Estos cuatro resultados son: Ninguna conversión. Esto sucede cuando se intenta convertir un tipo en sí mismo (por ejemplo, llamando a Convert..::.ToInt32(Int32) con un argumento de tipo Int32). En este caso, el método devuelve una instancia del tipo original. Objeto InvalidCastException. Esto sucede cuando no se admite una conversión determinada. Se produce una InvalidCastException para las conversiones siguientes: Conversiones de Char a Boolean, Single, Double, Decimal o DateTime. Conversiones de Boolean, Single, Double, Decimal o DateTime a Char. Conversiones de DateTime en cualquier otro tipo excepto String. Conversiones de cualquier otro tipo, excepto String en DateTime. Una conversión correcta. Para las conversiones entre dos tipos base diferentes no mostradas en los resultados anteriores, todas las conversiones de ampliación y todas las conversiones de restricción que no producen una pérdida de datos serán correctas y el método devolverá un valor del tipo base concreto. Objeto OverflowException. Esto sucede cuando una conversión de restricción produce una pérdida de datos. Por ejemplo, al intentar convertir una instancia Int32 cuyo valor es 10000 en un tipo Byte se produce una OverflowException porque 10000 está fuera del intervalo del tipo de datos Byte. No se producirá una excepción si la conversión de un tipo numérico produce una pérdida de precisión, es decir, la pérdida de algunos de los dígitos menos significativos. Sin embargo, la excepción se producirá si el resultado es mayor que lo que puede representar el tipo de valor devuelto del método de conversión. Por ejemplo, cuando un tipo Double se convierte en un tipo Single, se puede producir una pérdida de precisión pero no se produce ninguna excepción. Sin embargo, si la magnitud del tipo Double es demasiado grande para que un tipo Single lo represente, se produce una excepción de desbordamiento.