Conversión entre Tipos

Anuncio
Conversión entre Tipos
La conversión entre tipos permite comparar y copiar valores entre diferentes tipos. En esta lección
describiremos como convertir un tipo dado en otro.
Conversión en VB y C#
Existen 2 tipos de conversiones entre tipos:

Conversión implícita: Son aquellas conversiones entre tipos que no requieren una sintaxis
especial en el código. Este tipo de conversiones se emplean cuando tipo destino puede
acomodar todos los valores posibles del tipo origen. Visual Basic por defecto permite la
conversión implícita entre tipos independientemente si el tipo destino puede acomodar todos
los valores del tipo origen. C# prohíbe las conversiones implícitas que causen una pérdida de
rango o precisión. Ejemplos de conversiones implícitas:
C#
int i = 3;
double d = 3.1416;
d = i;
// ahora d = 3
Visual Basic
Dim i as Integer = 1
Dim d as Double = 3.1416
d = i ' ahora d = 3

Conversión explícita: Son aquellas conversiones entre tipos que requieren el uso de palabras
reservadas del lenguaje o de de tipos del framework que ayudan en la conversión. Este tipo de
conversiones se emplean cuando el tipo destino no puede acomodar todos los posibles valores
del tipo origen y por lo tanto se requiere expresar explícitamente en el código esa intención. Las
conversiones explícitas de emplean cuando se conoce de antemano que el valor origen puede
ser convertido al tipo destino sin pérdida o error. Existen muchas maneras de realizar
conversiones explícitas, entre ellas:
A nivel de .Net Framework, esto es independiente del lenguaje elegido
System.Convert
Provee métodos que permiten la conversión entre tipos que implementan la interface
System.IConvertible. Todos los tipos de datos del Framework implementan IConvertible.
tipo.ToString
Para convertir el valor de una instancia a una cadena que lo representa. Donde “tipo” es
cualquier tipo de dato del framework o definido por el usuario que sobrecarga la función
“ToString”. Si la conversión no es posible se lanza una excepción.
tipo.Parse
Para convertir una representación en cadena a un tipo específico. Donde “tipo” es cualquier tipo
de dato básico del framework. Si la conversión no es posible se lanza una excepción.
tipo.TryParse y tipo.TryParseExact
Es similar al método “Parse”, sólo que no lanza una excepción si la conversión falla sino que
devuelve el valor booleano false.
En C#
(tipo) expresión
Los paréntesis se pueden utilizar para especificar conversiones de tipos. Donde “tipo” es el tipo
al que deseamos convertir, que tiene definido operadores de conversión. De esta manera se
invoca explícitamente al operador de conversión de un tipo a otro. La operación de conversión
falla y genera un error en tiempo de compilación si no hay un operador de conversión definido
entre los tipos que se desea convertir.
as
La palabra reservada “as” se utiliza para realizar conversiones entre tipos por referencia
compatibles, si la conversión no es posible se retorna null en vez de lanzar una excepción.
En VB
CType(expresión, tipo)
Es análogo al operador de conversión (tipo) expresión de C#.
CBool(expresión), CInt(expresión), CStr(expresión), etc.
Permiten la conversión entre los diferentes tipos básicos de Visual Basic. Estas funciones con
compiladas en línea, proporcionando una mejor performance. Se recomienda utilizar estas
funciones de conversión de tipos de Visual Basic en preferencia a las que proporciona .Net
Framework con el método ToString() o la Clase Convert, ya que estas funciones están
diseñadas para una interacción óptima con Visual Basic.
DirectCast(expresión, tipo)
Es similar a CType pero sólo opera en tipos por referencia. Para que la conversión sea exitosa
se requiere una relación de herencia o de implementación entre los tipos de datos de los
argumentos de lo contrario se lanza una excepción. Lo que significa que un tipo debe heredar o
implementar el otro.
TryCast(expresión, tipo)
Es exactamente igual a DirectCast salvo que en vez de lanzar una excepción cuando la
conversión no es posible devuelve Nothing.
Boxing y Unboxing
Boxing: Convierte un tipo por valor a un tipo por referencia. Cuando necesitamos tratar a tipos por
valor como enteros, booleanos o estructuras como si fueran referencias se construye un objeto del tipo
System.Object y se copia el valor a esa referencia. Boxing ocurre implícitamente cuando un tipo por
valor es pasado como parámetro a un tipo object. Por ello es recomendable no diseñar métodos que
acepten parámetros del tipo System.Object sino crear tantas sobrecargas del método como con tipos
por valor a utilizar. La operación de Boxing, también ocurre implícitamente cuando se llaman a métodos
virtuales de una estructura que hereda de System.Object, como por ejemplo el método ToString(),
GetHash() y Equals. Por ello se recomienda sobrecargar estos métodos cuando se definen estructuras o
nuevos tipos por valor.
C#
int p = 123;
object o;
o = p; // Boxing implícito
o = (object) p; // Boxing explícito
Visual Basic
Dim p as Integer = 123;
Dim o as Object;
o = CType(p, Object) ' Boxing explícito
Unboxing: Convierte un tipo por referencia a un tipo por valor. Ocurre cuando se asigna una referencia
de un objeto a un tipo por valor. El valor almacenado en la referencia de objeto es copiado en la
ubicación que ocupa el tipo por valor.
C#
int p;
p = (int) o; // Unboxing explícito
Visual Basic
Dim p as Integer
p = CType(o, Integer) ' Unboxing explícito
La operación de Unboxing debe ser realizada con un operador de conversión explícito, si el valor
almacenado en la referencia de objeto no es del mismo tipo del que se especifica en la conversión se
generará una excepción.
Consejos:
Evitar aceptar los argumentos del tipo Object en métodos, para ello se recomienda el uso de Generics ó
de crear varias sobrecargas del método en cuestión que acepte varios tipos por valor.
Implementando Conversiones en Tipos Definidos por el Usuario
Cuando creamos una aplicación muchas veces definimos tipos de datos propios para facilitar el manejo
de información por parte de la misma; ahora bien, para lograr una integración óptima con el framework,
debemos de tener en cuenta detalles como el manejo de conversión entre tipos y otras funcionalidades
que pueden ser logradas a través de la sobre escritura de métodos.
En este caso vamos a seguir concentrados en el tema de interés que hemos venido estudiando: las
conversiones. Hay varias formas de implementar –o habilitar en su defecto- las conversiones en tipos
que han sido definidos por uno mismo, y la técnica que escojamos dependerá del tipo de conversión que
queramos hacer. Las formas más comunes se enlistan a continuación:

Podemos definir los operadores de conversión para simplificar las conversiones de ampliación o
reducción entre tipos numéricos. (Recordemos las densidades de los conjuntos que son
representados por tipos int o float por ejemplo)

Veamos ahora la sobre escritura de los métodos toString y Parse para conversión entre nuestra
clase y la clase String. Esta es una muy buena práctica dado que como programadores asumimos
que cada objeto tiene bien definida la forma de presentarse como String, a pesar de que
generalmente no se implemente y quedamos con el nombre de la clase únicamente.

Adicionalmente podemos implementar la interface System.IConvertible para habilitar las
conversiones utilizando el método System.Convert.
Ampliando un poco más sobre operadores de conversión, los podemos definir como los que nos van a
permitir asignar de otros tipos hacia el nuestro y viceversa directamente. Ahora bien, usaremos la forma
implícita si estamos ampliando dado que no vamos a perder precisión, y usaremos la forma explícita
cuando por el otro lado se puede dar perdida de precisión. (Para visualizar mejor este concepto,
pensemos en que creamos un tipo de datos llamado ”Fracción”, que nos permite guardar números
fraccionales en términos de numerador y denominador. Si queremos convertir de nuestro tipo de datos
a un tipo de datos float por ejemplo, no hay perdida de precisión -técnicamente-, mientras si lo pasamos
a un Integer es todo lo contrario)
Pensando ahora en la sobre escritura de métodos, simplemente implementamos la interface
IConvertible y dejamos que el IDE implemente automáticamente la interface (él agregará métodos
según la interface, de los cuales modificamos los que sean relevantes para nuestro tipo de datos.
Ejemplo: probablemente el método ToDateTime sea irrelevante para nuestra clase Fracción).
Descargar