いろいろ備忘録日記

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

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


引き続き、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 {
    }
}