サーチ…


備考

dynamicキーワードは、コンパイル時に型が分からない変数を宣言します。 dynamic変数には任意の値を含めることができ、値の型は実行時に変更できます。

「Metaprogramming in .NET」の帳で説明したように、C#にはdynamicキーワードのバッキングタイプはありません。

dynamicキーワードによって有効になる機能は、ローカル実行スコープのサイトコンテナ内でCallSiteオブジェクトを生成して使用するコンパイラアクションの賢明なセットです。コンパイラは、プログラマがCallSiteインスタンスを通じて動的オブジェクト参照として認識する内容を管理します。コンパイル時に動的な処理を行うパラメータ、戻り値の型、フィールド、およびプロパティには、動的使用のために生成されたことを示すメタデータが付いていますが、その基になるデータ型は常にSystem.Objectます。

動的変数の作成

dynamic foo = 123;
Console.WriteLine(foo + 234);
// 357    Console.WriteLine(foo.ToUpper())
// RuntimeBinderException, since int doesn't have a ToUpper method

foo = "123";
Console.WriteLine(foo + 234);
// 123234
Console.WriteLine(foo.ToUpper()):
// NOW A STRING

動的に戻る

using System;

public static void Main()
{
    var value = GetValue();
    Console.WriteLine(value);
    // dynamics are useful!
}

private static dynamic GetValue()
{
    return "dynamics are useful!";
}

プロパティを使用した動的オブジェクトの作成

using System;
using System.Dynamic;

dynamic info = new ExpandoObject();
info.Id = 123;
info.Another = 456;

Console.WriteLine(info.Another);
// 456

Console.WriteLine(info.DoesntExist);
// Throws RuntimeBinderException

コンパイル時に不明な特定の型の処理

次の出力と同等の結果が得られます。

class IfElseExample
{
    public string DebugToString(object a)
    {
        if (a is StringBuilder)
        {
            return DebugToStringInternal(a as StringBuilder);
        }
        else if (a is List<string>)
        {
            return DebugToStringInternal(a as List<string>);
        }
        else
        {
            return a.ToString();
        }
    }

    private string DebugToStringInternal(object a)
    {
        // Fall Back
        return a.ToString();
    }

    private string DebugToStringInternal(StringBuilder sb)
    {
        return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value: {sb.ToString()}";
    }

    private string DebugToStringInternal(List<string> list)
    {
        return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t" + string.Join(Environment.NewLine + "\t", list.ToArray())}";
    }
}

class DynamicExample
{
    public string DebugToString(object a)
    {
        return DebugToStringInternal((dynamic)a);
    }

    private string DebugToStringInternal(object a)
    {
        // Fall Back
        return a.ToString();
    }

    private string DebugToStringInternal(StringBuilder sb)
    {
        return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value: {sb.ToString()}";
    }

    private string DebugToStringInternal(List<string> list)
    {
        return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t" + string.Join(Environment.NewLine + "\t", list.ToArray())}";
    }
}

動的に有利なのは、新しいタイプのハンドルを追加するだけで、新しいタイプのDebugToStringInternalのオーバーロードを追加する必要があることです。また、手動でタイプにキャストする必要もありません。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow