Utilizzo del tipo dinamico (Guida per programmatori C#)

In Visual C# 2010 è stato introdotto un nuovo tipo, dynamic. Il tipo è statico, ma un oggetto di tipo dynamic ignora il controllo del tipo statico. Nella maggior parte dei casi, funziona come se disponesse del tipo object. In fase di compilazione, si presume che un elemento tipizzato come dynamic supporti qualsiasi operazione. Non è pertanto importante se l'oggetto ottiene il valore da un'API COM, da un linguaggio dinamico quale IronPython, dal modello DOM (Document Object Model) HTML, dalla reflection o da un altro elemento del programma. Se, tuttavia, il codice non è valido, vengono intercettati errori in fase di esecuzione.

Se, ad esempio, il metodo di istanza exampleMethod1 nel codice seguente dispone di un solo parametro, il compilatore riconosce che la prima chiamata al metodo, ec.exampleMethod1(10, 4), non è valida perché contiene due argomenti. La chiamata genera errori di compilazione. La seconda chiamata al metodo, dynamic_ec.exampleMethod1(10, 4), non viene controllata dal compilatore poiché il tipo di dynamic_ec è dynamic. Non viene, pertanto, segnalato alcun errore del compilatore. L'errore, tuttavia, non viene ignorato indefinitamente. Viene intercettato in fase di esecuzione e provoca un'eccezione in fase di esecuzione.

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) { }
}

Il ruolo del compilatore in questi esempi consiste nel raggruppare le informazioni sull'operazione prevista da ciascuna istruzione in relazione all'oggetto o all'espressione tipizzata come dynamic. In fase di esecuzione, le informazioni archiviate vengono esaminate e qualsiasi istruzione non valida provoca un'eccezione in fase di esecuzione.

Il risultato della maggior parte delle operazioni dinamiche è dynamic. Se, ad esempio, si posiziona il puntatore del mouse sull'utilizzo di testSum nell'esempio seguente, IntelliSense visualizza il tipo (variabile locale) dynamic testSum.

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

Le operazioni nelle quali il risultato non è dynamic includono le conversioni da dynamic a un altro tipo e le chiamate al costruttore che includono argomenti di tipo dynamic. Il tipo di testInstance, ad esempio, nella dichiarazione seguente è ExampleClass, non dynamic.

var testInstance = new ExampleClass(d);

Esempi di conversione sono illustrati nella sezione seguente, "Conversioni".

Conversioni

Le conversioni tra oggetti dinamici e altri tipi sono facili. In questo modo lo sviluppatore può passare dal comportamento dinamico a quello non dinamico e viceversa.

Un oggetto può essere convertito in tipo dinamico in modo implicito, come illustrato negli esempi seguenti.

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

Al contrario, una conversione implicita può essere applicata in modo dinamico a qualsiasi espressione di tipo dynamic.

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

Risoluzione dell'overload con argomenti di tipo dinamico

La risoluzione dell'overload si verifica in fase di esecuzione anziché in fase di compilazione se uno o più argomenti in una chiamata al metodo dispongono del tipo dynamic o se il ricevitore della chiamata al metodo è di tipo dynamic. Nell'esempio seguente, se il solo metodo exampleMethod2 accessibile è definito in modo che accetti un argomento di tipo stringa, l'invio di d1 come argomento non provoca un errore del compilatore, bensì un'eccezione in fase di esecuzione. La risoluzione dell'overload non riesce in fase di esecuzione perché il tipo in fase di esecuzione di d1 è int e exampleMethod2 richiede una stringa.

// 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

DLR (Dynamic Language Runtime) è una nuova API in .NET Framework 4. Fornisce l'infrastruttura che supporta il tipo dynamic in C# oltre all'implementazione di linguaggi di programmazione dinamici, quali IronPython e IronRuby. Per ulteriori informazioni su DLR, vedere Cenni preliminari su Dynamic Language Runtime.

Interoperabilità COM

Visual C# 2010 include diverse funzionalità che migliorano l'interoperabilità con le API COM, ad esempio le API di automazione di Office. Tra i miglioramenti è compreso l'utilizzo del tipo dynamic e di argomenti denominati e facoltativi.

Diversi metodi COM consentono la variazione nei tipi di argomento e nel tipo restituito designando i tipi come object. Per questo motivo è necessario il cast esplicito dei valori per la coordinazione con le variabili fortemente tipizzate in C#. Se si esegue la compilazione utilizzando l'opzione /link (opzioni del compilatore C#), l'introduzione del tipo dynamic consente di trattare le occorrenze di object nelle firme COM come se fossero di tipo dynamic e di evitare in tal modo gran parte del cast. Le istruzioni seguenti sono ad esempio in contrasto con la modalità di accesso a una cella in un foglio di calcolo di Microsoft Office Excel con il tipo dynamic e senza il 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];

Argomenti correlati

Titolo

Descrizione

dynamic (Riferimenti per C#)

Viene descritto l'utilizzo della parola chiave dynamic.

Cenni preliminari su Dynamic Language Runtime

Viene fornita una panoramica di DLR, un ambiente di runtime che estende Common Language Runtime (CLR) con un set di servizi per linguaggi dinamici.

Procedura dettagliata: creazione e utilizzo di oggetti dinamici (C# e Visual Basic)

Fornisce istruzioni dettagliate per la creazione di un oggetto dinamico personalizzato e per la creazione di un progetto che accede a una libreria IronPython.

Procedura: accedere agli oggetti di interoperabilità di Office utilizzando le funzionalità di Visual C# 2010 (Guida per programmatori C#)

Viene illustrato come creare un progetto che utilizza argomenti denominati e facoltativi, il tipo dynamic e altri miglioramenti che semplificano l'accesso agli oggetti API di Office.