martes, 7 de julio de 2015

Enlace Dinámico en C# - Parte 4: Expresiones Dinámicas

Índice

0. Introducción
1. Expresiones Dinámicas
1.1 Retorno void
1.2 Operandos dinámicos
1.3 Casos excepciones en expresiones dinámicas
2. Llamadas Dinámicas sin Receptores Dinámicos
3. Conclusiones
4. Glosario
5. Literatura & Enlaces

0. Introducción

En esta cuarta entrega de la serie de artículos de Enlace Dinámico en C# veremos cómo los elementos de programa (i.e., campos, propiedades, métodos, eventos, constructores, indezadores, operadores) y operaciones (e.g., conversión) pueden ser invocados de forma dinámica. A esto le sumaremos la exploración de excepciones en donde expresión dinámica retorna una expresión estática. Luego exploraremos el uso de expresiones sin receptores dinámicos.
  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. Expresiones Dinámicas

Los elementos de programa que son posibles construir con el lenguaje de programación C# permiten ser invocados de forma dinámica. Entre ellos tenemos:
  • Campos
  • Constructores
  • Eventos
  • Indexadores
  • Métodos
  • Operadores
  • Propiedades
Además, expresiones que involucran la conversión entre tipos, también están permitidos en invocaciones dinámicas.

1.1 Retorno void

En [1] nos dicen que las expresiones dinámicas que retornan void no pueden formar parte de una asignación. Esto está prohíbido: en tiempo de ejecución se genera la excepción RuntimeBinderException (Enlace Dinámico en C# - Parte 1: Introducción). Por ejemplo si tratamos de hacer algo como esto:

dynamic lista = new List();
var resultado = lista.Add(new Libro("Los hermanos Karámazov", "Fyódor Dostoyevski");

En tiempo de ejecución se lanzará la excepción RuntimeBinderException debido a que el método Add de List retorna void. Recordemos que lo mismo sucede en tiempo de compilación cuando intentamos hacer algo como esto:

FileInfo archivo = new FileInfo("LosHermanosKaramov.mobi");
var resultado = archivo.Refresh();

La implementación del método Refresh [3] de la clase FileInfo retorna void. En tiempo de compilación se generá el error CS0815 [6]:

Cannot assign void to an implicitly-typed local variable

1.2 Operandos dinámicos

Una expresión que incluya uno o más operandos dinámicos es generalmente dinámica. Esto se debe al argumento dado en [1]:
"...since the effect of absent type information is cascading."
Para demostrarlo, recurramos a este fragmento de código:

dynamic x = 2;
var resultado = x * 3;

Aquí, cuando se efectúe la operación del lado derecho

x * 3

El tipo estático reconocido por el compilador para resultado será dynamic.

1.3 Casos excepcionales en expresiones dinámicas

1.3.1 Casting

Para las conversiones explícitas, el compilador asignará un tipo estático. Por ejemplo:

dynamic x = 5;
var y = (int) x;

La variable definida como var será estáticamente de tipo int.

1.3.2 Instanciación

Debemos tener presente que la invocación de un constructor de un tipo genera expresiones estáticas. E inclusive cuando uno o más argumentos sean de tipo dinámico [1]:

dynamic cantidad = 19;
var libro = new Libro("Los hermanos Karámazov", "Fyódor Dostoyevski", cantidad);

En esta situación, estáticamente, el compilador reconocerá libro (var) como de tipo Libro.

2. Llamadas Dinámicas sin Receptores Dinámicos

Como receptor podemos referirnos a un objeto capaz de infocar una función dinámica. Por ejemplo:

dynamic x = ...;
x.MetodoDinamico();

En este caso x es el receptor de una llamada a una función dinámica: MetodoDinamico.

Sin embargo, hay excepciones en donde es posible invocar funciones (en término general) estáticas con argumentos dinámicos; por ejemplo [1]:
  • Métodos estáticos
  • Constructores de instancia
  • Métodos de instancia invocados desde un receptor identificado con un tipo estático
Para comprender mejor este concepto podemos adaptar el ejemplo que se encuentra en [1]:

Ejemplo de uso:


Notemos que los argumentos de las llamadas a los métodos sobrecargados MostrarConsola (líneas 13 y 14) reciben como argumento valores de tipo dynamic. Debido a la ausencia de receptores dinámicos en tiempo de compilación el compilador es capaz estáticamente de resolver las llamadas a los métodos sobrecargados MostrarEnConsola.


Por otra parte, debido a que el chequeo se realiza en tiempo de compilación en un programa como el siguiente se generan errores compilación:

Ejemplo de uso:

Archivo C# ResolucionEstatica.cs [Enlace alternativo]:



Notemos que a pesar de que las llamadas a:
  • MostrarEnConsola, y 
  • MostrarEnDialogo
involucran tipos dinámicos, el compilador es capaz de resolver estáticamente los errores de compilación que se pudieran generar. En este caso lo logra debido a que las funciones no tienen especificado un receptor dinámico.

3. Conclusiones

En este artículo C# hemos explorado los básicos para comprender las sutilezas en la invocación de miembros con expresiones dinámicas. La promoción a tipo dinámico el resultado de la evaluación de expresiones que involucran tipos dinámicos. Estamos advertidos de la restricción de intento erróneo de asignación de retorno void de una expresión dinámica (e.g., list.Add(...)). Al final vimos cómo en casos excepcionales el compilador es capaz de resolver estáticamente las invocaciones a expresiones que no involucran un receptor dinámico.


La quinta y última parte de esta serie de artículos de Enlace Dinámico lo dedicaremos principalmente a estos temas:
  • Tipos estáticos en expresiones dinámicas, 
  • Funciones no-invocables, y 
  • Representación de dinámicos en tiempo de ejecución.

4. Glosario

  • Expresión dinámica
  • Expresión estática
  • Función
  • Invocación
  • Miembro
  • Receptor
  • Resolución dinámica
  • Resolución estática

5. 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]: Enlace Dinámico en C#: Introducción - http://ortizol.blogspot.com/2015/07/enlace-dinamico-en-csharp-parte-1.html
[3]: FileSystemInfo.Refresh Method (System.IO) - https://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.refresh(v=vs.110).aspx
[4]: Compiler Error CS0815 - https://msdn.microsoft.com/en-us/library/bb384140(v=vs.90).aspx


J

No hay comentarios:

Publicar un comentario

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