C#のdynamicキーワードがどのようなものであり、なぜそれが登場したのかについてMads Torgersen氏(リンク)のプレゼンテーションを見ることができる。そこではdynamicキーワードと同じようなことができ、だが最終的に採用されなかった 別の代替案についても触れられている。
C# 4では新しいメタ型である「dynamic」によってレイトバインディングがサポートされることになる。この型で直接宣言されている変数、あるいはこの型 を返す関数の戻り値は、自動的にレイトバインディングするように処理される。これはVisual Basicで「object」型で変数を宣言するのに似ているが、CTS(共通型システム)やCOM以外のどんな型システムもサポートできるようになって いる。
この機能の目的が、最近は動的バインディングとも呼ばれるレイトバインディングをサポートするためであるというのは一つの重要な点だ。動的型付けはC#の機能リストに明示されてないが、動的バインディングをサポートする結果として動的型付けも可能になる。
ただしリフレクションが代替できるようにはなってない。リフレクションには多くの異なる種類が存在するという問題がある。Reflection名前空間を使ってメソッドを呼ぶのは、ScriptObjectのメソッドを呼ぶのとは異なるのだ。Ruby/Pythonでは専用のメソッドがある。
dynamycキーワード以外に考えられた方法にはチルダ動的演算子を付けるものがあった。残念ながら、この方法だとコードがすぐに見苦しくなってしまう。キャストや配列のインデックスや数学演算子について使おうとする場合は殊更だ。
object d = GetDynamicObject(); string result = ~(string) d ~[ d~.Length ~- 1];
考えられた別の方法はdynamicコンテキストだ。こう設計するとunsafeコンテキストやuncheckedコンテキストと同じように、任意のブ ロックに 「dynamic」を付けることができる。この場合の問題は静的なコードと動的なコードを混在させるのが難しくなることだ。混在させるコードは次のような 感じになってしまう
dynamic { //some dynamic code static { //some statically bound code dynamic { //some dynamic code in some static code } //some more statically bound code } //some more dynamic code }
3つめは伝搬性のある式だ。そのような式を使うと、その性質上、動的であることが関係箇所に伝搬して伝わることになる。
object d = GetDynamicObject(); string result = (string) d[ dynamic(d).Length - 1];
ここで彼らの選んだ構文は完璧とはいえない。動的であるという情報は、動的呼び出しが適用される場所に書く必要はない。そのような情報は変数の宣言時に利用可能であればいいのだ。したがってこの式を使うのであれば、次のようになるだろう。
dynamic d = GetDynamicObject(); string result = (string) d[d.Length - 1];
この設計で問題となったのは安全でなくなってしまうことだった。このような動的呼び出しでも例外を投げられるようにするには、自分で大量かつバグの入りやすいリフレクションロジックを書かないといけなくなってしまうからだ。
別の案はメタ型でなくdynamic修飾子を作ることだった。この場合、次のコードを書いた時に、Fooのメソッドにアーリーバインドを指定することがで きても、それ以外はすべてレイトバインドになる。これは極端なケースではパフォーマンスの改善になるかもしれないが、必要以上に複雑さを増してしまうこと になる。
dynamic Foo d = GetDynamicFooObject();
ある式に対して動的であることを指定できるのであれば、全ての式に対してもその指定が可能なはずだ。たとえば次のような式である。
- メソッド呼び出し
- 呼び出し機構
- メンバアクセス
- 演算子の適用
- インデックス
ここに入らないものは明らかで、変換とコンストラクタだ。これらは静的コンテキストを返すはずだ。変換は動的言語ランタイム型のシステムでも実現できるが、その場合変換の結果は特殊な型になってしまう。