dynamic 型の使用 (C# プログラミング ガイド)

Visual C# 2010 では、dynamic という新しい型が導入されています。 この型は静的な型ですが、dynamic 型のオブジェクトは静的な型チェックをバイパスします。 ほとんどの場合、object 型を使用する場合と同様に機能します。 コンパイル時には、dynamic として型指定された要素はあらゆる操作をサポートすると見なされます。 したがって、オブジェクトが COM API、IronPython などの動的言語、HTML ドキュメント オブジェクト モデル (DOM: Document Object Model)、リフレクション、プログラムの他の場所のいずれから値を取得するのかを考慮する必要はありません。 ただし、コードが無効な場合には、実行時にエラーが検出されます。

たとえば、次のコードの exampleMethod1 インスタンス メソッドにパラメーターが 1 つしかない場合、ec.exampleMethod1(10, 4) メソッドへの最初の呼び出しは引数を 2 つ含むため、コンパイラはこの呼び出しを無効と認識します。 この呼び出しではコンパイル エラーが発生します。 dynamic_ec.exampleMethod1(10, 4) メソッドの 2 番目の呼び出しは、dynamic_ec の型が dynamic であるため、コンパイラによって確認されません。 そのため、コンパイル エラーは報告されません。 ただし、このエラーがいつまでたっても検出されないということではありません。 実行時に検出されて実行時例外が発生します。

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

これらの例におけるコンパイラの役割は、dynamic として型指定されたオブジェクトまたは式に対して各ステートメントが何を実行しようとしているかについて、情報をまとめてパッケージ化することです。 格納された情報が実行時に調べられ、無効なステートメントがある場合は実行時例外が発生します。

ほとんどの動的操作は、結果自体が dynamic です。 たとえば、次の例では testSum を使用している箇所にマウス ポインターを置くと、IntelliSense によって型が (ローカル変数) dynamic testSum と表示されます。

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

結果が dynamic でない操作として、dynamic から他の型への変換や、dynamic 型の引数を含むコンストラクター呼び出しがあります。 たとえば、次の宣言の testInstance の型は dynamic ではなく ExampleClass です。

var testInstance = new ExampleClass(d);

次の「変換」のセクションに変換例を示します。

変換

動的オブジェクトとその他の型との変換は簡単です。 そのため、開発者は動的な動作と動的でない動作を切り替えることができます。

次の例に示すように、任意のオブジェクトを動的な型に暗黙的に変換できます。

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

逆に、dynamic 型の任意の式に暗黙的な変換を動的に適用できます。

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

dynamic 型の引数を使用したオーバーロードの解決

メソッド呼び出しの 1 つ以上の引数が dynamic 型を指定している場合、またはメソッド呼び出しのレシーバーが dynamic 型である場合は、コンパイル時ではなく実行時にオーバーロードの解決が実行されます。 次の例では、唯一のアクセス可能な exampleMethod2 メソッドが文字列引数を受け取るように定義されている場合、d1 を引数として送信すると、コンパイラ エラーは発生しませんが、実行時例外が発生します。 d1 の実行時の型は int であり、exampleMethod2 には文字列が必要であるため、オーバーロードの解決は実行時に失敗します。

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

動的言語ランタイム

動的言語ランタイム (DLR: Dynamic Language Runtime) は .NET Framework 4 の新しい API です。 DLR は、C# の dynamic 型だけでなく、IronPython や IronRuby などの動的プログラミング言語の実装もサポートするインフラストラクチャを提供します。 DLR の詳細については、「動的言語ランタイムの概要」を参照してください。

COM 相互運用

Visual C# 2010 には、Office オートメーション API などの COM API との相互運用エクスペリエンスを強化する複数の機能があります。 この機能強化には、dynamic 型の使用、および名前付き引数と省略可能な引数の使用が含まれます。

多くの COM メソッドでは、型を object と指定することによって、引数の型と戻り値の型にバリエーションを持たせることができます。 このためには、C# で厳密に型指定された変数と連携できるように値の明示的なキャストが必要でした。 /link (C# コンパイラ オプション) オプションを使用してコンパイルする場合、dynamic 型が導入されて COM シグネチャの object のオカレンスを dynamic 型と同様に処理できるようになったため、ほとんどのキャストを回避できます。 たとえば、Microsoft Office Excel スプレッドシートのセルに dynamic 型を使用してアクセスする方法と、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];

関連トピック

タイトル

説明

dynamic (C# リファレンス)

dynamic キーワードの使用法について説明します。

動的言語ランタイムの概要

DLR の概要について説明します。DLR は動的言語の一連のサービスを共通言語ランタイム (CLR: Common Language Runtime) に追加するランタイム環境です。

チュートリアル: 動的オブジェクトの作成と使用 (C# および Visual Basic)

動的なカスタム オブジェクト、および IronPython ライブラリにアクセスするプロジェクトを作成するための詳細な手順について説明します。

方法: Visual C# 2010 の機能を使用して Office 相互運用オブジェクトにアクセスする (C# プログラミング ガイド)

名前付き引数と省略可能な引数、dynamic 型、および Office API オブジェクトへのアクセスを簡単にするその他の強化機能を使用してプロジェクトを作成する方法について説明します。