lunes, 6 de julio de 2015

Enlace Dinámico en C# - Parte 3: La Palabra Clave Dynamic, Conversiones, y var vs. dynamic

Índice

0. Introducción
1. La Palabra Clave dynamic
2. Conversiones Dinámicas
3. var vs. dynamic
3.1 Diferencia fundamental
3.2 Tiempo de compilación vs. tiempo de ejecución
3.3 Conversiones
4. Conclusiones
5. Glosario
6. Literatura & Enlaces

0. Introducción

Esta tercera parte de la serie de artículos de Enlace Dinámico estará dedicada a tratar la palabra clave dynamic, conversiones entre dynamic y otros tipos de datos, y haremos una comparación de uso de var (deducción de tipos en tiempo de compilación) y dynamic.
  1. Introducción al Enlace Dinámico, Enlace estático vs enlace dinámico, RuntimeBinderException
  2. Enlace Personalizado, Enlace de Lenguaje
  3. La Palabra Clave dynamic, Conversiones, Diferencia entre var y dynamic
  4. Expresiones Dinámicas, Expresiones Dinámicas sin Receptores Dinámicos
  5. Tipos Estáticos en Expresiones Dinámicas, Funciones Non-Invocables

1. La Palabra Clave dynamic

Desde la versión 4.0 de Microsoft .NET Framework en C# podemos utilizar la palabra clave dynamic [2] para la resolución de miembros de tipos en tiempo de ejecución. En tiempo de compilación la comprobación de tipos, castingboxing y unboxing, y demás operaciones de chequeo son descartados por el compilador.

En este ejemplo podemos encontrar la diferencia entre la comprobación en tiempo de compilación y en tiempo de ejecución.

Archivo C# PruebaDynamicObject.cs [Enlace alternativo]:


En la línea 10 declaramos una variable de dynamic -dyn-, y la inicializamos con la literal entera 1; en la siguiente línea una instancia de object -obj-, con el valor entero 1 (boxing). Más adelante sobre la línea 13 sumamos 3 al valor 1 que tiene encapsulado el tipo dynamic (línea 10).

Continuando, si intentamos hacerlo mismo con object, es decir 

obj = ((object)obj) + 3;


el compilador de C# generará el error CS0019 [3] debido a que no es posible aplicar el operador + sobre un tipo object y una literal entera (en su lugar, era necesario hacer casting((object)obj) + 3). Notemos que esto ha ocurrido en tiempo de compilación, y por supuesto, nos genera una ventaja significativa sobre la comprobación de tipos en tiempo de ejecución. Demostrémolo a través del intento de invocar un miembro no definido sobre la variable dynamic -dyn-:

dyn.MetodoInexistente ()

La compilación del programa en el archivo de código fuente PruebaDynamicObject.cs no generará ningún error en tiempo de compilación, sin embargo, cuando intentemos ejecutar el assembly:

.\PruebaDynamicObject.exe

obtendremos el siguiente mensaje de error:

Intento de invocar método inexistente en una variable dynamic
Figura 1. Intento de invocar método inexistente en una variable dynamic.
En el mensaje de error que aparece en la Figura 1 se informa que ha ocurrido la excepción RuntimeBinderException (N:Microsoft.CSharp.RuntimeBinder[6] que se traduce en el intento de enlazar (binding) miembros de un tipo inexistentes en tiempo de ejecución.

Antes de finalizar, sobre el artículo en DotNetPerls [2, 7] nos advierten sobre el uso de dynamic:
Dynamic is advanced functionality. It can be useful. But usually it should be avoided. It erases many benefits of the C# language.
Además:
The dynamic keyword influences compilation. A dynamic variable, parameter or field can have any type. Its type can change during runtime. The downside is that performance suffers and you lose compile-time checking.

2. Conversiones Dinámicas

Las variables declaradas con dynamic tienen la capacidad de efectuar conversiones implícitas. Veamos este fragmento de código:

int entero32Bits = 7;
dynamic dyn = entero;
long entero64Bits = dyn; // Conversión implícita: no se requiere casing


En la tercera línea la conversión implícita del objeto dynamic a long está permitada debido a que int  es implícitamente convertible a long. En general, los tipos estáticos de destino deben soportar la conversión del tipo implícito dinámico de origen.


En contraste, cuando intentamos

int entero32Bits = 7;
dynamic dyn = entero;
short entero16Bits = dyn; // Se lanza la excepción RuntimeBinderException


se lanza la excepción RuntimeBinderException (Enlace Dinámico en C# - Parte 1: Introducción) debido que el tipo estático de destino no permite conversión implícita entre int a short.

3. var vs. dynamic

3.1 Diferencia fundamental

Podemos resumir la diferencia de var y dynamic como en [1]:
var says, "Let the compiler figure out the type."
dynamic says, "Let the runtime figure out the type."

3.2 Tiempo compilación vs. tiempo de ejecución

A nivel de código podemos diferenciar estas dos construcciones así:

dynamic x = "xCSw"; // Tipo estático: dynamic; Tipo en ejecución: string
var y = "xCSw"; // Tipo estático: string; Tipo en ejecución: string
int i = x; // Error en tiempo de ejecución
int j = y; // Error en tiempo de compilación

3.3 Conversiones

En tiempo de compilación puede establecerse el tipo de una variable declarada con var en dynamic:

dynamic x = "xCSw";
var y = x; // Tipo estático de la variable y dynamic
int z = y; // Error en tiempo de ejecución

La segunda línea de código es permitida por el compilador ya que la conversión de un tipo dynamic a var está permitida: el compilador asignara a y el tipo dynamic. En cuanto a la tercera línea, la conversión falla: no está permitida la conversión de string a int.

[Nota: Para conocer más acerca de var recomiendo la lectura de este artículo var - Variables Locales de Tipo Deducido Implícitamente en C#.]

4. Conclusiones

Estudiamos varios aspectos importantes de la palabra clave (o reservada) dynamic: la disposición de esta palabra en .NET para agregar capacidades dinámicas a nuestro código, por ejemplo, la agregación de miembros en tiempo de ejecución (demostrado en la segunda parte de esta serie de Enlace Dinámico), las conversiones implícitas permitidas, y la comparación entre var y dynamic.

5. Glosario

  • .NET
  • Conversión implícita
  • dynamic
  • Tiempo de compilación
  • Tiempo de ejecución
  • var

6. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Using Type dynamic (C# Programming Guide) - https://msdn.microsoft.com/en-us/library/dd264736.aspx
[3]: Compiler Error CS0019 - http://msdn.microsoft.com/en-us/library/a63h61ky.aspx
[4]: Enlace Dinámico en C# - Parte 1: Introducción - http://ortizol.blogspot.com/2015/07/enlace-dinamico-en-csharp-parte-1.html
[5]: Enlace Dinámico en C# - Parte 2: Enlace de Lenguaje y Personalizado - http://ortizol.blogspot.com/2015/07/enlace-dinamico-en-csharp-parte-2-enlace-de-lenguaje-y-personalizado.html
[6]: var - Variables Locales de Tipo Deducido Implícitamente en C# - http://ortizol.blogspot.com/2013/09/var-variables-locales-de-tipo-deducido.html


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.