|
|
連載:C# 4入門
第1回 dynamic型
株式会社ピーデー 川俣 晶
2010/07/16 |
 |
|
dynamic型と匿名型
匿名型は、名前もなく、定義も存在しない型のオブジェクトを作るための機能である。厳密にいえば、型は存在するのだが、C#のソース・コードでアクセスできる形態では存在しないのである。しかし、それが有効利用できる範囲はあまり広くはなかった。1つのメソッドの外に持ち出すことは不可能ではないが、持ち出してしまうと、利用にはリフレクションが必要だったからである。
しかし、dynamic型が一挙に問題を解決してくれた。dynamic型として返せば、簡単に内容にアクセスできるのである。
using System;
class Program
{
private static dynamic GetObject()
{
return new { YourName = "Arashi隊員", YourScore = 1000 };
}
static void Main(string[] args)
{
dynamic a = GetObject();
Console.WriteLine("{0}のスコアは{1}点です。",
a.YourName, a.YourScore);
}
}
|
|
リスト6 dynamic型と匿名型を使ったオブジェクトの受け渡し |
もちろん、C#としての定義がない型なので、名前を書き間違えてもコンパイル時にエラーは出ず、実行時に例外が発生することになる。
dynamic型と動的言語
dynamic型を使うとソース・コードがスマートになる事例はほかにもある。
例えば、.NET Framework上でPython言語を使用可能にする「IronPython」というソフトウェアが存在するが、これを用いるとC#からPythonで書かれたコードを簡単に利用できる。
以下、実際にPythonで記述されたメソッドを呼び出した事例を見てみよう。なお、Visual Studio 2010とIronPython 2.6.1を使用している。
また、前準備としては以下の手順を必要とする。
- IronPythonに含まれているアセンブリのIronPython.dll、Microsoft.Dynamic.dll、Microsoft.Scripting.dllへの参照を追加しておく
- テキスト・ファイルをプロジェクトに追加して、sample.pyというファイル名を付けておく
ここで以下の2つのファイルを書き込む。
using System;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
class Program
{
static void Main(string[] args)
{
ScriptRuntime py = Python.CreateRuntime();
dynamic sample = py.UseFile(@"sample.py);
dynamic r = sample.getWeapon();
Console.WriteLine("{0} has a {1}.", r.name, r.weapon);
}
}
|
|
リスト7 Program.cs |
class WeaponInfo:
name=0
weapon=0
def getWeapon():
a = WeaponInfo()
a.name = "Cyber Ryo"
a.weapon = "Colt Python"
return a
|
|
リスト8 sample.py |
Cyber Ryo has a Colt Python.
|
|
リスト8の実行結果 |
さて、このプログラムは、2つのメンバ(nameとweapon)を持つオブジェクトを結果として受け取っている。ここで問題となるのは、受け取ったオブジェクトの定義がどこにあるのかである。
もちろん、sample.pyにあるWeaponInfoクラスの定義がそれに当たるのだが、C#コンパイラがコンパイル時に参照できるのはC#の定義か、あるいは.NET Frameworkで作成されたアセンブリである。つまり、Pythonのソース・コードは参照できないので、このクラスの定義はコンパイル時に参照できない。
しかし、dynamic型を用いることで、このソース・コードは大幅に簡素化されている。コンパイラは参照できない定義でも、ランタイムは実行中にそのようなメンバが存在していることを動的に認識し、dynamic型を経由すればそのメンバの値も使用できるのである。
まとめ
今回の内容をまとめておく。
- dynamic型は実行時に型を解釈する
- コンパイル時に定義を知らないオブジェクトが持つ情報にアクセスできる
- 名前さえ一致していれば、どのクラスの定義でも、定義がなくてもアクセスできる
- 匿名型の使い勝手が向上する
- 動的言語との相互運用に便利
- つづりの間違いは実行するまでエラーにならない
- 定義不要で扱えるためソースは短くなるが、性能面では静的な定義に劣る
dynamic型は必ずしも不可能を可能にした型というわけではない。それ以前でも、リフレクションで同じような機能を記述することはできたが、dynamic型はそのためのハードルを大きく下げてくれたのである。
実行効率が悪いことを気にするのであれば、対策はある。並列実行である。増え続けるコアを同時に活用すれば性能低下は最小限に食い止められる。次回からはそのための機能を見ていこう。
Insider.NET 記事ランキング
本日
月間