Sök…


Anmärkningar

Det dynamic nyckelordet deklarerar en variabel vars typ inte är känd vid sammanställningstiden. En dynamic variabel kan innehålla valfritt värde, och värdetyp kan ändras under körning.

Som nämnts i boken "Metaprogrammering i .NET" har C # inte någon stödjande typ för det dynamic nyckelordet:

Funktionen som aktiveras av det dynamic nyckelordet är en smart uppsättning kompilatoråtgärder som avger och använder CallSite objekt i webbplatsbehållaren i det lokala exekveringsområdet. Kompilatorn hanterar vad programmerare uppfattar som dynamiska objektreferenser genom dessa CallSite instanser. Parametrarna, returtyper, fält och egenskaper som får dynamisk behandling vid sammanställningstiden kan markeras med vissa metadata för att indikera att de genererades för dynamisk användning, men den underliggande datatypen för dem kommer alltid att vara System.Object .

Skapa en dynamisk variabel

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

Återvändande dynamisk

using System;

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

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

Skapa ett dynamiskt objekt med egenskaper

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

Hantera specifika typer okända vid sammanställningstiden

Följande utgångsekvivalent resultat:

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())}";
    }
}

Fördelen med dynamiken är att lägga till en ny typ för att hantera bara kräver att man lägger till en överbelastning av DebugToStringInternal av den nya typen. Eliminerar också behovet av att manuellt kasta den till typen också.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow