Compartir vía


Uso del tipo dynamic

El tipo dynamic es un tipo estático, pero un objeto de tipo dynamic omite la comprobación de tipos estáticos. En la mayoría de los casos, funciona como si tuviera el tipo object. El compilador da por supuesto que un elemento dynamic admite cualquier operación. Por consiguiente, no tiene que determinar si el objeto obtiene su valor de una API COM, de un lenguaje dinámico como IronPython, del Document Object Model (DOM) de HTML, de la reflexión o de otro lugar en el programa. Sin embargo, si el código no es válido, se muestran errores 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 porque contiene dos argumentos. La llamada genera 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 consiguiente, no se notifica ningún error del compilador. Sin embargo, el error no pasa inadvertido indefinidamente. Aparece en tiempo de ejecución y genera una excepción en tiempo de ejecución.

static void Main(string[] args)
{
    ExampleClass ec = new ExampleClass();
    // The following call to exampleMethod1 causes a compiler error
    // if exampleMethod1 has only one parameter. Uncomment the line
    // to see the error.
    //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 lo que cada instrucción se propone para la expresión o el objeto dynamic. El entorno de ejecución examina la información almacenada y cualquier instrucción que no sea válida provoca una excepción en tiempo de ejecución.

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

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

Entre las operaciones en las que el resultado no es de tipo dynamic, se incluyen:

  • Conversiones de dynamic a otro tipo.
  • Llamadas de constructor que incluyen argumentos de tipo dynamic.

Por ejemplo, el tipo de testInstance en la declaración siguiente es ExampleClass, no dynamic:

var testInstance = new ExampleClass(d);

Conversiones

Las conversiones entre objetos dinámicos y de otro tipo son fáciles. Las conversiones permiten al desarrollador cambiar entre el comportamiento dinámico y no dinámico.

Puede convertir cualquiera en dynamic implícitamente, como se muestra en los ejemplos siguientes.

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

Por el contrario, puede aplicar dinámicamente cualquier conversión implícita 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 y no en tiempo de compilación si uno o varios argumentos de una llamada de método tienen el tipo dynamic o si el receptor de la llamada de método es de tipo dynamic. En el ejemplo siguiente, si el único método exampleMethod2 accesible toma un argumento de cadena, al enviar d1 como argumento no se produce un error del compilador, pero sí se genera una excepción en tiempo de ejecución. La resolución de sobrecarga no se produce en tiempo de ejecución porque el tipo en tiempo de ejecución de d1 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) 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 sobre el entorno DLR, vea Información general acerca de Dynamic Language Runtime.

Interoperabilidad COM

Muchos métodos COM permiten variaciones en los tipos de argumento y el tipo de valor devuelto mediante la designación de los tipos como object. La interoperabilidad COM requiere la conversión explícita de los valores para coordinarse con variables fuertemente tipadas en C#. Si se compila con la opción EmbedInteropTypes (opciones del compilador de C#) la introducción del tipo dynamic le permite tratar las repeticiones de object en las signaturas de COM como si fueran de tipo dynamic y así evitar gran parte de la conversión. Para obtener más información sobre el uso del tipo dynamic con objetos COM, consulte el artículo Acceso a los objetos de interoperabilidad de Office mediante características de C#.

Title Descripción
dynamic Describe el uso de la palabra clave dynamic.
Información general sobre Dynamic Language Runtime Ofrece información general sobre DLR, que es un entorno en tiempo de ejecución que agrega un conjunto de servicios para lenguajes dinámicos en Common Language Runtime (CLR).
Tutorial: Crear y usar objetos dinámicos Ofrece instrucciones paso a paso para crear un objeto dinámico personalizado y para crear un proyecto que acceda a una biblioteca de IronPython.