読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

C#4.0の追加機能-02(dynamic-02, 動的プログラミング, runtime lookup, overload resolution, IDispatch)

C#


引き続き、dynamicについてです。
が、今回は前回の内容と、あまり変わりません。


dynamicを用いて、動的なプログラミングを行う際に
.NETは内部でRuntime Lookupという動作を行います。


これは、dynamicとして定義されたオブジェクトが実際には
何の型なのかを調べる処理です。


ホワイトペーパーに記述されている内容だと以下の過程を
踏んでいくようです。

  1. COM Objects
    1. IDispatch経由でアクセスする。
  2. Dynamic Objects
    1. IDynamicObject経由でアクセスする。
  3. Plain Objects
    1. Reflection経由でアクセスする。


また、オーバーロードメソッドを呼び出したりする際も
解決が行われます。(Overload resolutionというようです。)


解決手順は、上記の内容で行われ、最終的に合致した
オーバーロードメソッドが実行に呼ばれます。


以下、サンプルです。

using System;

namespace DynamicLookup02 {

    class Program {

        static void Main(string[] args) {
            (new Program()).Execute();
        }

        private void Execute() {
            //
            // Runtime Lookup
            //
            // dynamicを利用している場合、目的のオブジェクトを特定するために
            // 以下の手順で型の特定が行われる。
            //
            // 1.COM Objects
            //      そのオブジェクトがCOMオブジェクトの場合は、IDispatch経由でアクセスが行われる。
            // 
            // 2.Dynamic Objects
            //      そのオブジェクトがIDynamicObjectを実装している場合、そのオブジェクト自身に問い合わせる。
            //      (このインターフェースは、IronPythonやIronRubyのような動的言語にてサポートされる)
            //
            // 3.Plain Objects
            //      そのオブジェクトが普通の.NET Objectである場合、Reflectionを用いてアクセスが行われる。
            //
            // 下記の場合は、Plain ObjectであるのでReflectionを用いて実行時にアクセスが行われる。
            //
            SampleA a = new SampleA();
            dynamic b = new SampleB();

            a.Method1(b);

            //
            // Overload resolution
            //
            // 引数の型がdynamicの状態で、オーバーロードメソッドを呼び出すと
            // Overload resolution(オーバーロード解決)が行われる。
            //
            // 下記の例では、dynamicである変数a2は実際にはSampleAのインスタンスで
            // あるので、実行時に解決が行われSampleBクラスの
            //          internal void Execute(SampleA a)
            // が呼び出される。
            //
            dynamic a2 = new SampleA();
            dynamic b2 = new SampleB();

            b2.Execute(a2);

            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    }

    class SampleA {

        public void Method1(dynamic b) {
            b.Execute(this);
        }
    }

    class SampleB {

        internal void Execute(SampleA a) {
            Console.WriteLine("Sample B : {0}", a.ToString());
        }

        internal void Execute(SampleC c) {
            Console.WriteLine("Sample B : {0}", c.ToString());
        }
    }

    class SampleC {
    }
}