dynamic 型の使用
dynamic
型は静的な型ですが、dynamic
型のオブジェクトは静的な型チェックをバイパスします。 ほとんどの場合、object
型を使用する場合と同様に機能します。 コンパイラは、dynamic
要素がすべての操作をサポートしていることを前提としています。 したがって、オブジェクトが COM API、IronPython などの動的言語、HTML ドキュメント オブジェクト モデル (DOM)、リフレクション、プログラムの他の場所のいずれから値を取得するのかを決定する必要はありません。 ただし、コードが無効な場合には、実行時にエラーが発生します。
たとえば、次のコードの 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 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) { }
}
これらの例におけるコンパイラの役割は、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
に変換できます。
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) は、C# での dynamic
型と、IronPython や IronRuby などの動的プログラミング言語の実装を提供します。 DLR の詳細については、「動的言語ランタイムの概要」を参照してください。
COM 相互運用
多くの COM メソッドでは、型を object
と指定することによって、引数の型と戻り値の型にバリエーションを持たせることができます。 COM 相互運用では、C# での厳密に型指定された変数との連携に値の明示的なキャストが必要です。 EmbedInteropTypes (C# コンパイラ オプション) オプションを使用してコンパイルする場合、dynamic
型が導入されて COM シグネチャの object
のオカレンスを dynamic
型と同様に処理できるようになったため、ほとんどのキャストを回避できます。 COM オブジェクトで dynamic
型を使用する方法の詳細については、C# 機能を使用して Office 相互運用オブジェクトにアクセスする方法に関するの記事を参照してください。
関連記事
Title | 説明 |
---|---|
dynamic | dynamic キーワードの使用法について説明します。 |
動的言語ランタイムの概要 | DLR の概要について説明します。DLR は動的言語の一連のサービスを共通言語ランタイム (CLR) に追加するランタイム環境です。 |
チュートリアル: 動的オブジェクトの作成と使用 | 動的なカスタム オブジェクト、および IronPython ライブラリにアクセスするプロジェクトを作成するための詳細な手順について説明します。 |
.NET