Ejercicio: Exploración de la conversión y la coerción de tipos de datos
- 30 minutos
Hay varias técnicas para realizar una conversión de tipos de datos. Debe escoger la técnica en función de su respuesta a dos preguntas importantes:
- En función del valor, ¿es posible que el intento de cambiar el tipo de datos del valor produzca una excepción en tiempo de ejecución?
- En función del valor, ¿es posible que el intento de cambiar el tipo de datos del valor provoque una pérdida de información?
En este ejercicio analizaremos estas preguntas, las implicaciones de sus respuestas y la técnica que debe usar cuando necesite cambiar el tipo de datos.
Preparación del entorno de programación
Este módulo incluye actividades prácticas que le guiarán en el proceso de compilación y ejecución de código de demostración. Se recomienda realizar las actividades con Visual Studio Code como entorno de desarrollo. El uso de Visual Studio Code para estas actividades ayuda a familiarizarse con la escritura y la ejecución de código en un entorno de desarrollo que usan profesionales de todo el mundo.
Nota
Si ha completado otros módulos de Microsoft Learn de esta serie de C#, es posible que ya haya creado una carpeta de proyecto para los ejemplos de código. Si ese es el caso, puede omitir la siguiente sección de pasos y eliminar el código del archivo Program.cs usado para un ejercicio anterior.
Nota
Los ejemplos de código de este ejercicio están diseñados en función de la configuración cultural en-US y usan un punto (.) como separador decimal. La compilación y ejecución del código con una configuración de referencia cultural que usa separadores decimales diferentes (como una coma ,) pueden dar resultados o errores inesperados. Para corregir este problema, reemplace los separadores decimales de punto en los ejemplos de código por el separador decimal local (por ejemplo, ,).
Además, si desea ejecutar un programa con la configuración de referencia cultural "en-US", agregue el siguiente código al principio del programa using System.Globalization; y, después de cualquier otra instrucción using, agregue CultureInfo.CurrentCulture = new CultureInfo("en-US");.
Abra Visual Studio Code.
Puede usar el menú Inicio de Windows (o un recurso equivalente en otro sistema operativo) para abrir Visual Studio Code.
En el menú Archivo de Visual Studio Code, seleccione Abrir carpeta.
En el cuadro de diálogo Abrir carpeta , vaya a la carpeta Escritorio de Windows.
Si tiene una ubicación de carpeta diferente donde guarda los proyectos de código, úsela. Para este ejercicio, lo importante es tener una ubicación fácil de encontrar y recordar.
En el cuadro de diálogo Abrir carpeta , seleccione Seleccionar carpeta.
Si ve un cuadro de diálogo de seguridad que pregunta si confía en los autores, seleccione Sí.
En el menú Terminal de Visual Studio Code, seleccione Nuevo terminal.
Observe que el símbolo del sistema del terminal muestra la ruta de acceso de la carpeta actual. Por ejemplo:
C:\Users\someuser\Desktop>Para crear una aplicación de consola en una carpeta especificada, en el símbolo del sistema del terminal escriba
dotnet new console -o ./CsharpProjects/TestProjecty presione Entrar.Este comando de la CLI de .NET usa una plantilla de programa de .NET para crear un nuevo proyecto de aplicación de consola de C# en la ubicación de carpeta especificada. El comando crea las carpetas CsharpProjects y TestProject, y usa TestProject como nombre del archivo
.csproj.En el panel EXPLORADOR, expanda la carpeta CsharpProjects .
Debería ver la carpeta TestProject y dos archivos, un archivo de programa de C# denominado Program.cs y un archivo de proyecto de C# denominado TestProject.csproj.
En el panel EXPLORADOR, para ver el archivo de código en el panel Editor, seleccione Program.cs.
Elimine las líneas de código que contiene.
Durante este módulo usará este proyecto de consola de C# para crear, compilar y ejecutar ejemplos de código.
Cierre el panel del terminal.
Pregunta: ¿es posible que el intento de cambiar el tipo de datos del valor produzca una excepción en tiempo de ejecución?
El compilador de C# intenta acomodar su código, pero siempre evita las operaciones que puedan producir una excepción. Cuando comprenda la principal preocupación del compilador de C#, le será más fácil entender por qué funciona de una manera determinada.
Escriba código que intente agregar un int y string y guarde el resultado en un int.
Asegúrese de que ha abierto Visual Studio Code y de que Program.cs se muestra en el panel Editor.
Nota
Program.cs debe estar vacío. Si no es así, seleccione y elimine todas las líneas de código.
En el Editor de Visual Studio Code, escriba el código siguiente:
int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);Aquí estamos intentando agregar los valores
2y4. El valor4es de tipostring. ¿Funcionará?En el menú Archivo de Visual Studio Code, seleccione Guardar.
El archivo Program.cs debe guardarse antes de compilar o ejecutar el código.
En el panel EXPLORER, para abrir un terminal en la ubicación de la carpeta TestProject, haga clic con el botón derecho en TestProject y, a continuación, seleccione Abrir en terminal integrado.
Debe abrirse un panel de terminal y debe incluir un símbolo del sistema que muestre que el terminal está abierto en la ubicación de la carpeta TestProject.
En el símbolo del sistema del terminal, para ejecutar el código, escriba
dotnet runy presione Entrar.Debería ver la salida aproximada siguiente
C:\Users\someuser\Desktop\csharpprojects\TestProject\Program.cs(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int'Nota
Si ve un mensaje que indica "No se ha podido encontrar un proyecto para ejecutar", asegúrese de que el símbolo del sistema del terminal muestra la ubicación de carpeta TestProject prevista. Por ejemplo:
C:\Users\someuser\Desktop\csharpprojects\TestProject>Dedique un minuto a considerar por qué el compilador no pudo ejecutar el primer ejemplo de código.
La parte importante del mensaje de error,
(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int', indica que el problema radica en el uso del tipo de datosstring.Pero ¿por qué no soluciona el error el compilador de C#? Después de todo, podemos hacer lo contrario para concatenar un número con un valor
stringy guardarlo en una variable de cadena. A continuación, cambiaremos el tipo de datos de la variableresultdeintastring.Actualice el código en el editor de Visual Studio Code de la siguiente manera:
int first = 2; string second = "4"; string result = first + second; Console.WriteLine(result);Guarde el archivo de código y use Visual Studio Code para ejecutar el código.
Debemos observar la siguiente salida:
24La salida es matemáticamente incorrecta, pero se completa combinando los valores como los caracteres "2" y "4".
Examine, una vez más, el primer ejemplo de código donde la variable
resultes de tipoint. El código con el mensaje de error.int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);¿Por qué el compilador de C# no puede determinar que queremos tratar la variable
secondque contiene4como un número y no como un tipostring?
Los compiladores realizan conversiones seguras
El compilador de C# detecta un posible problema en el proceso. La variable second es de tipo string, por lo que podría establecerse en otro valor como "hello". Si el compilador de C# intentara convertir "hello" en un número, esto provocaría una excepción en tiempo de ejecución. Para evitar esta posibilidad, el compilador de C# no realiza implícitamente la conversión de string a int.
Desde la perspectiva del compilador de C#, la operación más segura sería convertir int en un valor string y realizar una concatenación en su lugar.
Si piensa realizar sumas mediante una cadena, el compilador de C# requiere que tome un control más explícito del proceso de conversión de datos. En otras palabras, le obliga a involucrarse más para que adopte las precauciones adecuadas para abordar la posibilidad de que la conversión pueda producir una excepción.
Si necesita cambiar un valor del tipo de datos original a un nuevo tipo de datos y el cambio podría producir una excepción en tiempo de ejecución, debe realizar una conversión de datos.
Para realizar la conversión de datos, puede emplear varias técnicas:
- Usar un método auxiliar en el tipo de datos.
- Usar un método auxiliar en la variable.
- Uso de los métodos de la clase
Convert
Veremos algunos ejemplos de estas técnicas de conversión de datos más adelante en esta unidad.
Pregunta: ¿es posible que el intento de cambiar el tipo de datos del valor provoque una pérdida de información?
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:int myInt = 3; Console.WriteLine($"int: {myInt}"); decimal myDecimal = myInt; Console.WriteLine($"decimal: {myDecimal}");Guarde el archivo de código y use Visual Studio Code para ejecutar el código.
Debería ver el siguiente resultado:
int: 3 decimal: 3La clave de este ejemplo es esta línea de código:
decimal myDecimal = myInt;Cualquier valor
intpuede adaptarse fácilmente dentro de un tipodecimal, de modo que el compilador realiza la conversión.El término conversión de ampliación significa que está intentando convertir un valor de un tipo de datos que podría contener menos información a un tipo de datos que puede contener más información. En este caso, un valor almacenado en una variable de tipo
intconvertido en una variable de tipodecimalno pierde información.Cuando sepa que va a realizar una conversión de ampliación, puede confiar en la conversión implícita. El compilador controla las conversiones implícitas.
Realización de una coerción
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:decimal myDecimal = 3.14m; Console.WriteLine($"decimal: {myDecimal}"); int myInt = (int)myDecimal; Console.WriteLine($"int: {myInt}");Para realizar una coerción, se usa el operador de coerción
()para encerrar un tipo de datos y se coloca junto a la variable que se quiere convertir (ejemplo:(int)myDecimal). Se realiza una conversión explícita al tipo de datos de coerción definido (int).Guarde el archivo de código y use Visual Studio Code para ejecutar el código.
Debería ver el siguiente resultado:
decimal: 3.14 int: 3La clave de este ejemplo es esta línea de código:
int myInt = (int)myDecimal;La variable
myDecimalcontiene un valor con precisión después del separador decimal. Al agregar la instrucción de coerción(int), estamos indicando al compilador de C# que sabemos que es posible que perdamos esa precisión, pero que, en este caso, no pasa nada. Le indica al compilador que está realizando una conversión intencionada, una conversión explícita.
Determinación de si una conversión es "de ampliación" o "de restricción"
El término conversión de restricción significa que está intentando convertir un valor de un tipo de datos que puede contener más información a un tipo de datos que puede contener menos información. En este caso, podría perder información como precisión (es decir, el número de valores después del separador decimal). Un ejemplo es convertir un valor almacenado en una variable de tipo decimal en una variable de tipo int. Si imprimimos los dos valores, notaríamos la pérdida de información.
Cuando sepamos que va a realizar una conversión de restricción, debemos llevar a cabo una coerción. La conversión es una instrucción que indica al compilador de C# que usted sabe que es posible que se pierda precisión, pero está dispuesto a aceptarlo.
Si no está seguro de si se pierden datos en la conversión, escriba código para realizar una conversión de dos maneras diferentes y observe los cambios. Los desarrolladores suelen escribir pruebas pequeñas para comprender mejor los comportamientos, como se muestra en el ejemplo siguiente.
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:decimal myDecimal = 1.23456789m; float myFloat = (float)myDecimal; Console.WriteLine($"Decimal: {myDecimal}"); Console.WriteLine($"Float : {myFloat}");Guarde el archivo de código y use Visual Studio Code para ejecutar el código.
Debería ver una salida similar a esta:
Decimal: 1.23456789 Float : 1.2345679Puede observar en la salida que convertir
decimalenfloates una conversión de restricción, ya que se pierde precisión.
Realización de conversiones de datos
Anteriormente se indicó que un cambio de valor de un tipo de datos a otro puede provocar una excepción en tiempo de ejecución y que se debe realizar la conversión de datos. Para las conversiones de datos se pueden usar tres técnicas:
- Usar un método auxiliar en la variable.
- Usar un método auxiliar en el tipo de datos.
- Uso de los métodos de la clase
Convert
Uso de ToString() para convertir un número en string
Todas las variables de tipo de datos tienen un método ToString(). Lo que hace el método ToString() depende de cómo se implemente este en un tipo determinado. No obstante, en la mayoría de los primitivos, realiza una conversión de ampliación. Aunque esto no es estrictamente necesario (puesto que podemos basarnos en la conversión implícita en la mayoría de los casos), puede comunicar a otros desarrolladores que comprende lo que está haciendo y que es a propósito.
A continuación, se muestra un ejemplo rápido del uso del método ToString() para convertir explícitamente valores int en string.
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:int first = 5; int second = 7; string message = first.ToString() + second.ToString(); Console.WriteLine(message);Guarde el archivo de código y use Visual Studio Code para ejecutar el código. Al ejecutar el código, la salida debe mostrar una concatenación de los dos valores:
57
Conversión de un objeto string en int mediante el método Parse() auxiliar
La mayoría de los tipos de datos numéricos tienen un método Parse(), que convierte una cadena en el tipo de datos especificado. En este caso, usaremos el método Parse() para convertir dos cadenas en valores int y, después, los sumaremos.
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:string first = "5"; string second = "7"; int sum = int.Parse(first) + int.Parse(second); Console.WriteLine(sum);Guarde el archivo de código y use Visual Studio Code para ejecutar el código. Al ejecutar el código, la salida debe mostrar una suma de los dos valores:
12Tómese un minuto para intentar detectar el posible problema con el ejemplo de código anterior. ¿Qué ocurre si alguna de las variables
firstosecondse establece como un valor que no se puede convertir enint? Se produce una excepción en tiempo de ejecución. El compilador y el entorno de ejecución de C# esperan el planeamiento con antelación para evitar conversiones "ilegales". Podemos mitigar la excepción en tiempo de ejecución de varias maneras.La forma más sencilla es usar
TryParse(), una versión mejorada del métodoParse().
Conversión de un objeto string en int mediante la clase Convert
La clase Convert tiene muchos métodos auxiliares para convertir un valor de un tipo en otro. En el siguiente ejemplo de código, vamos a convertir un par de cadenas en valores de tipo int.
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:string value1 = "5"; string value2 = "7"; int result = Convert.ToInt32(value1) * Convert.ToInt32(value2); Console.WriteLine(result);Guarde el archivo de código y use Visual Studio Code para ejecutar el código.
Debería ver el siguiente resultado:
35Nota
¿Por qué se llama
ToInt32()el método? ¿Por qué noToInt()?System.Int32es el nombre del tipo de datos subyacente de la biblioteca de clases .NET que el lenguaje de programación C# asigna a la palabra claveint. Como la claseConverttambién forma parte de la biblioteca de clases .NET, se llama por su nombre completo, no por su nombre de C#. Al definir los tipos de datos como parte de la biblioteca de clases .NET, varios lenguajes de .NET (como Visual Basic, F#, IronPython, etc.) pueden compartir los mismos tipos de datos y las mismas clases en la biblioteca de clases .NET.El método
ToInt32()tiene 19 versiones sobrecargadas que permiten aceptar prácticamente todos los tipos de datos.Aquí hemos usado el método
Convert.ToInt32()con una cadena, pero probablemente debería usarTryParse()siempre que sea posible.Por lo tanto, ¿cuándo debemos usar la clase
Convert? Se recomienda usar la claseConvertpara convertir números fraccionarios en números enteros (int) porque redondea de la manera prevista.
Comparación de la coerción y conversión de un objeto decimal en int
En el ejemplo siguiente se muestra lo que sucede cuando intenta convertir un valor decimal en uno int (una conversión de restricción) en lugar de usar el método Convert.ToInt32() para convertir ese valor decimal en int.
Elimine o use el operador
//de comentario de línea para comentar el código del paso anterior del ejercicio y agregue el código siguiente:int value = (int)1.5m; // casting truncates Console.WriteLine(value); int value2 = Convert.ToInt32(1.5m); // converting rounds up Console.WriteLine(value2);Guarde el archivo de código y use Visual Studio Code para ejecutar el código.
Debería ver el siguiente resultado:
1 2
La coerción trunca y la conversión redondea
Al coercer int value = (int)1.5m;, se trunca el valor "float" y, por ende, el resultado es 1, lo que significa que el valor de después del decimal se omite por completo. Podríamos cambiar el float literal por 1.999m y el resultado de la conversión sería el mismo.
Al usar Convert.ToInt32() para convertir, el valor "float" literal se redondea correctamente a 2. Si cambiáramos el valor literal a 1.499m, se redondearía a 1.
Resumen
Hemos tratado varios conceptos importantes sobre la conversión y la coerción de datos:
- Evitar un error en tiempo de ejecución al realizar una conversión de datos
- Realización de una coerción explícita para indicar al compilador que comprende el riesgo de pérdida de datos
- Confíe en que el compilador realizará una coerción implícita a la hora de llevar a cabo una conversión de ampliación.
- Use el operador de coerción
()y el tipo de datos para llevar a cabo una coerción (por ejemplo,(int)myDecimal). - Use la clase
Convertcuando quiera llevar a cabo una conversión de restricción y redondear, pero que no se trunque la información.