cci dynamicの使用詳細

7199 ワード

dynamicはFrame Work 4.0の新しい特性です。dynamicの出現によって、C〓は弱い言語タイプの特性を持たせました。コンパイラはコンパイル時にはタイプのチェックを行わず、コンパイル期間はデフォルトdynamicオブジェクトで任意の特性をサポートします。例えば、GetDynamicObject方法で戻ってきたオブジェクトが何も知らなくても、下記のようにコードの呼び出しができます。コンパイラはエラーがありません。

dynamic dynamicObject = GetDynamicObject();
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());
正しい使い方といえば、まず間違いを指摘すべきです。
varというキーワードを持ってdynamicと比較する人がよくいます。実際には、varとdynamicは完全に二つの概念です。一緒に比較するべきではありません。varは実際にコンパイル期間で私たちに投げられた「シンタックスキャンディー」です。コンパイルされると、var変数の実際のタイプに自動的にマッチして、実際のタイプで変数の説明を交替します。これはコード化の時に実際のタイプで説明しているように見えます。dynamicはコンパイルされた後、実際にはobjectタイプですが、コンパイラはdynamicタイプを特殊処理して、コンパイルの間に任意のタイプの検査を行わないで、タイプの検査を運行期間に入れました。
これはvisual studioのエディタの窓から分かります。var宣言の変数では、「インテリジェント感知」をサポートしています。Visual studitionはvarタイプの実際のタイプを推定できますが、dynamic宣言の変数では「インテリジェント感知」をサポートしていません。コンパイラはその運行期間のタイプについて何も知らないからです。dynamic変数には「インテリジェント感知」を使い、「この操作は実行時に解析します」とヒントを与えます。
dynamic変数はobject変数であることをILコードで検証します。ここではILコードを貼りません。もちろん、コンパイラもdynamic声明を処理して直接object変数を区別します。
dynamicは、相互操作性を簡略化するためにMSDNによって誇張されているということに基づいて、一部の開発者に誤解されていると思います。多くの開発者はCOM+、OFFICE二次開発などのコードに接触しないので、dynamicの応用理由が急に必要です。では、日常的な開発において、dynamicは価値があると思います。
タイプ変換
Dynamicタイプのインスタンスと他のタイプのインスタンスとの間の遷移は簡単であり、開発者はdynamicと非dynamicの挙動の間で簡単に切り替えることができる。いずれの例も、dynamicタイプのインスタンスに暗黙的に変換することができ、次の例を参照してください。

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();
Conversely、an implicit conversion can be dynamically aplied to any expressition of type dynamic.
逆もまた、タイプがdynamicであるいかなる表現も、他のタイプに暗黙的に変換することができる。英語の翻訳

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;
方法にはdynamicタイプのパラメータが含まれています。
呼び出し方法がdynamicタイプのオブジェクトを伝達するか、または呼び出しられたオブジェクトがdynamicタイプの場合、リロードの判定は実行時にコンパイルではない場合があります。
 動的言語実行時(dynamic langage runtime DLR)
NET Fraamewark 4 Beta 1の新しいAPIのセットは、czhiのdynamicタイプへのサポートを提供しています。また、IreonPythoonやIreonRubyなどの動的プログラミング言語を実現しています。
dynamicは反射を簡単にすることができます。
以前私たちは反射をこのように使いました。

public class DynamicSample
{
public string Name { get; set; }

public int Add(int a, int b)
{
return a + b;
}
}
DynamicSample dynamicSample = new DynamicSample(); //create instance      ,       
var addMethod = typeof(DynamicSample).GetMethod("Add");
int re = (int)addMethod.Invoke(dynamicSample, new object[] { 1, 2 });
今は簡略化された書き方があります。

dynamic dynamicSample2 = new DynamicSample();
int re2 = dynamicSample2.Add(1, 2);
私達はこのような簡略化に対して納得できないかもしれません。結局コードはそれほど減少していないように見えますが、効率的で優美な二つの特性を考慮すれば、dynamicの優位性が現れます。コンパイラはdynamicを最適化しました。キャッシュなしの反射効率よりもずっと速いです。どうしても比較したいなら、上記の二つのコード(Addメソッドの部分を呼び出す)を1000,000運転すれば結論が出ます。
dynamicのキーワードがやっと出てきた時、本当に役に立たないと思いました。いつもcomと対話して行きます。避けるしかないです。
        その後、徐々にいくつかの使用の収穫があったとしても、この商品は本当に鋭いですね、このいくつかの例では、レンガを投げて玉を引くために使用されます。
1.代わりにXXXX.GetType().GetProperty(YYY).GetValue(XXX)

static object GetPerson()
{
    return new Person { Name = "Leo" };
} 
たまにこのようなobjectに戻る不運なコード(特に反射に関わる時)に出会うことができます。この時に私達はまたその中のある属性を訪問します。それは大変です。今はdynamicがあって気分が良くなりました。

object objPerson = GetPerson();
var objName =  objPerson.GetType().GetProperty("Name").GetValue(objPerson);
Console.WriteLine(objName);

dynamic dynPerson = GetPerson();
var dynName = dynPerson.Name;
Console.WriteLine(dynName);
もう一つの利点は性能がある程度上がることです。

Watch = new Stopwatch();
            Watch.Start();
            for (int i = 0; i < 1000000; i++)
            {
                objName = objPerson.GetType().GetProperty("Name").GetValue(objPerson);
            }
            Watch.Stop();
            Console.WriteLine(Watch.Elapsed);


            Watch.Restart();
            for (int i = 0; i < 1000000; i++)
            {
                dynName = dynPerson.Name;
            }
            Watch.Stop();
            Console.WriteLine(Watch.Elapsed);
大体の結果は下図のように速くなりました。

2.キャッチャーのインターフェースが設計されていないコードを救う運が悪い子供。
        例えば、ここにはN個のWCFサービスがあり、N個のオブジェクトの集合に戻っています。これらのオブジェクトは大丈夫です。実はもう一つの関係があります。運が悪い子供はEntity Framewarkに生成されたクラスは自動的にあるインターフェースを継承しません。
        ここで一つの例を挙げると、まず次の2つの不幸なクラスがあります。同じstringタイプのnameはインターフェースを抽出することができます。同じ名前ですが、異なるタイプのIDです。まったく関係のないAgeとPriceです。

public class Person
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }

        public static List<Person> GetPersonList()
        {
            return new List<Person>
            {
                new Person{ Name = "Leo1" , Age = 10 },
                new Person{ Name = "Leo2" , Age = 20 },
                new Person{ Name = "Leo3" , Age= 30 }
            };
        }
    }

    public class Car
    {
        public Guid ID { get; set; }

        public string Name { get; set; }

        public double Price { get; set; }

        public static List<Car> GetCarList()
        {
            return new List<Car>
            {
                new Car{ Name = "Focus1" , Price = 100 },
                new Car{ Name = "Focus2" , Price = 200 },
                new Car{ Name = "Focus3" , Price = 300 }
            };
        }
    }
        2つのstatic方法で異なるタイプのList<T>を返して、WCFで最も一般的な呼び出しをシミュレートします。

static void Main(string[] args)
        {
            List<dynamic> list = new List<dynamic>();
            //       WCF  ,      WCF   list
            Person.GetPersonList().ForEach((p) => list.Add(p));
            TestDynamic2(list,"Leo2");

            list = new List<dynamic>();
            //       WCF  ,      WCF   list
            Car.GetCarList().ForEach((c) => list.Add(c));
            TestDynamic2(list,"Focus3");

            Console.ReadKey();
        }

        private static void TestDynamic2(List<dynamic> list,string name)
        {
            //        ID Name  
            dynamic first = list.OrderBy(d => d.ID).FirstOrDefault(d => d.Name.Contains(name));

            //         ,     ,      ,           
            if (first is Person)
            {
                Console.WriteLine(first.Age);
            }
            else
            {
                Console.WriteLine(first.Price);
            }
        }
以上はc菙dynamicの使用についての詳しい内容です。c葑dynamicの使用に関する資料は他の関連記事に注目してください。