|
|
連載:C# 4入門
第8回 ExpandoObjectを継承した動的拡張できるクラス
株式会社ピーデー 川俣 晶
2011/02/10 |
|
|
メソッド・モドキの追加
ExpandoObjectはメソッドやプロパティを動的に追加することはできない。しかし、メソッドに関してはそれっぽいことができる。デリゲート型の値を追加することで、呼び出すことができるわけである。
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic x = new ExpandoObject();
x.DoIt = (Action)(() => Console.WriteLine("I'm first!"));
x.DoIt();
x.DoIt = (Action)(() => Console.WriteLine("I'm second!"));
x.DoIt();
}
}
|
|
リスト7 |
ラムダ式はそれだけでは型が決まらないため、「(Action)」というキャストが要求されているが、それ以外は別に難しいこともないだろう。デリゲート型の値を差し替えることで、実行される内容も動的に差し替えが可能になっている。
引数がある場合もAction型やFunc型を利用すれば問題はない。
using System;
using System.Dynamic;
class Program
{
static void Main(string[] args)
{
dynamic x = new ExpandoObject();
x.DoIt = (Func<string,string>)
((s) => string.Format("{0} first!",s));
Console.WriteLine(x.DoIt("I'm"));
}
}
|
|
リスト8 |
これだけである。簡単な割に使い出があるといえる。しかし、乱用はあまりお勧めではない。動的な機能はエラー・チェックが実行時になり、どうしても問題の発覚が遅れがちだからである。
まとめ
今回のまとめ。
- 単に実行時に決まるメンバに値を格納するだけなら、ダイナミック・オブジェクトよりExpandoObjectの方がずっと簡単に書ける
- ダイナミック・オブジェクトと違って、ExpandoObjectを利用する場合は継承して処理方法を記述する必要がない
- 名前と値に関するさまざまな処理は、ExpandoObjectに実装されたインターフェイスで処理できる
- しかし、多くの場合、インターフェイスにキャストしないと呼び出せない
- メンバの名前と値のペアはLINQでクエリすることもできる
さて、このExpandoObjectも、やはり出番が多いかといえば微妙だ。メンバを実行時に自由に追加できるということは、コンパイル時にはメンバが確定しないということであり、当然IntelliSenseの候補にも動的なメンバは出てこない。
「A」や「B」あるいが「DoIt」ぐらいならまだしも、長い名前を付けると自分ですべて打たねばならない。「IsAlradyJoinedWithUltraSuperDeluxeMan」というような長い名前を付けてしまうと使い勝手は極端に落ちていく。
通常は可読性優先で長い名前を付けるのもよいが(それでもC#の機能をフル活用するとコードをかなり短くできる)、動的に扱う場合はIntelliSenseで入力できないので、スペルミスが混入する確率は跳ね上がる。
やはり、この機能も「中間言語としてのC#」で生きてくるのではないかと思う。一部の動的な言語は、ExpandoObjectと相性がよさそうである。そういう言語からC#への変換プログラムはかなり書きやすくなったのだろうと思う。
しかし、リフレクションを多用する動的なプログラミングをしていれば、その助けになるという可能性もあるだろう。いずれにしても、そのあたりにいくらでもある普通のプログラムで使って生きる機能ではなさそうである。使うことよりも、使い所を見つけることで評価されそうな機能かもしれない。
Insider.NET 記事ランキング
本日
月間