Uso de tipo dinámico (Guía de programación de C#)

Visual C# 2010 presenta un nuevo tipo, dynamic. Se trata de un tipo estático, pero un objeto de tipo dynamic omite la comprobación de tipos en tiempo de compilación. En la mayoría de los casos, funciona como si tuviera el tipo object. En tiempo de compilación, se supone que un elemento de tipo dynamic admite cualquier operación. Por lo tanto, no tiene que preocuparse de si el objeto obtiene su valor de una API de COM, de un lenguaje dinámico como IronPython, de DOM (Document Object Model) HTML, de la reflexión o de cualquier otra parte del programa. Sin embargo, si el código no es válido, los errores se detectan en tiempo de ejecución.

Por ejemplo, si el método de instancia exampleMethod1 del código siguiente solo tiene un parámetro, el compilador reconoce que la primera llamada al método (ec.exampleMethod1(10, 4)) no es válida, ya que contiene dos argumentos. La llamada provoca un error del compilador. El compilador no comprueba la segunda llamada al método, dynamic_ec.exampleMethod1(10, 4), porque el tipo de dynamic_ec es dynamic. Por lo tanto, no se notifica ningún error del compilador. Sin embargo, el error no pasa desapercibido indefinidamente. Se detecta en tiempo de ejecución y produce una excepción en tiempo de ejecución.

static void Main(string[] args)
{
    ExampleClass ec = new ExampleClass();
    // The following line causes a compiler error if exampleMethod1 has only
    // one parameter.
    //ec.exampleMethod1(10, 4);

    dynamic dynamic_ec = new ExampleClass();
    // The following line is not identified as an error by the
    // compiler, but it causes a run-time exception.
    dynamic_ec.exampleMethod1(10, 4);

    // The following calls also do not cause compiler errors, whether 
    // appropriate methods exist or not.
    dynamic_ec.someMethod("some argument", 7, null);
    dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
    public ExampleClass() { }
    public ExampleClass(int v) { }

    public void exampleMethod1(int i) { }

    public void exampleMethod2(string str) { }
}

El rol del compilador en estos ejemplos consiste en empaquetar información sobre la acción que cada una de las instrucciones propone para el objeto o la expresión de tipo dynamic. En tiempo de ejecución, la información almacenada se examina y cualquier instrucción no válida produce una excepción en tiempo de ejecución.

El resultado de la mayoría de las operaciones dinámicas es dynamic en sí. Por ejemplo, si coloca el puntero del mouse sobre el uso de testSum en el siguiente ejemplo, IntelliSense muestra el tipo (variable local) dynamic testSum.

dynamic d = 1;
var testSum = d + 3;
// Rest the mouse pointer over testSum in the following statement.
System.Console.WriteLine(testSum);

Las operaciones en las que el resultado no es dynamic incluyen las conversiones de dynamic en otro tipo, así como llamadas a constructor que incluyen argumentos de tipo dynamic. Por ejemplo, el tipo de testInstance en la siguiente declaración es ExampleClass, no dynamic.

var testInstance = new ExampleClass(d);

En la siguiente sección, "Conversiones", se muestran ejemplos de conversión.

Conversiones

Las conversiones entre los objetos dinámicos y de otros tipos son fáciles. Esto permite al desarrollador cambiar entre un comportamiento dinámico y no dinámico.

Cualquier objeto se puede convertir en el tipo dinámico implícitamente, como se muestra en los siguientes ejemplos.

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

Por el contrario, una conversión implícita se puede aplicar dinámicamente a cualquier expresión de tipo dynamic.

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;

Resolución de sobrecarga con argumentos de tipo dinámico

La resolución de sobrecarga se produce en tiempo de ejecución en lugar de en tiempo de compilación si uno o más de los argumentos de una llamada de método tiene el tipo dynamic o si el receptor de dicha llamada es de tipo dynamic. En el ejemplo siguiente, si el único método exampleMethod2 accesible se define de forma que tome un argumento de cadena, el envío de d1 como argumento no produce un error del compilador, pero sí una excepción en tiempo de ejecución. La resolución de sobrecarga origina un error en tiempo de ejecución porque el tipo de d1 en tiempo de ejecución es int y exampleMethod2 requiere una cadena.

// Valid.
ec.exampleMethod2("a string");

// The following statement does not cause a compiler error, even though ec is not
// dynamic. A run-time exception is raised because the run-time type of d1 is int.
ec.exampleMethod2(d1);
// The following statement does cause a compiler error.
//ec.exampleMethod2(7);

Dynamic Language Runtime

Dynamic Language Runtime (DLR) es una nueva API en .NET Framework 4. Proporciona la infraestructura que admite el tipo dynamic en C# y también la implementación de lenguajes de programación dinámicos como IronPython e IronRuby. Para obtener más información acerca de DLR, vea Información general acerca de Dynamic Language Runtime.

Interoperabilidad COM

Visual C# 2010incluye varias características que mejoran la experiencia de interoperar con las API de COM, como las API de automatización de Office. Entre las mejoras se encuentra el uso del tipo dynamic, así como de los argumentos con nombre y opcionales.

Muchos métodos COM permiten la variación en los tipos de argumento y el tipo de valor devuelto mediante la designación de los tipos como object. Esto ha hecho necesario la conversión explícita de los valores para coordinarlos con las variables fuertemente tipadas en C#. Si compila con la opción /link (Opciones del compilador de C#), la introducción del tipo dynamic permite tratar las apariciones de object en los prototipos COM como si fueran de tipo dynamic y evitar así gran parte de la conversión. Por ejemplo, en las instrucciones siguientes se contrasta la forma en que se tiene acceso a una celda en una hoja de cálculo de Microsoft Office Excel con el tipo dynamic y sin el tipo dynamic.

// Before the introduction of dynamic.
((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name";
Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];
// After the introduction of dynamic, the access to the Value property and
// the conversion to Excel.Range are handled by the run-time COM binder.
excelApp.Cells[1, 1].Value = "Name";
Excel.Range range2010 = excelApp.Cells[1, 1];

Temas relacionados

Título

Descripción

dynamic (Referencia de C#)

Describe el uso de la palabra clave dynamic.

Información general acerca de Dynamic Language Runtime

Proporciona información general sobre DLR, un entorno en tiempo de ejecución que agrega un conjunto de servicios para lenguajes dinámicos a Common Language Runtime (CLR).

Tutorial: Crear y utilizar objetos dinámicos (C# y Visual Basic)

Proporciona instrucciones paso a paso para crear un objeto dinámico personalizado y crear un proyecto que obtiene acceso a una biblioteca de IronPython.

Cómo: Tener acceso a objetos de interoperabilidad de Office mediante las características de Visual C# 2010 (Guía de programación de C#)

Muestra cómo crear un proyecto que usa argumentos con nombres y opcionales, el tipo dynamic y otras mejoras que simplifican el acceso a los objetos de la API de Office.