Zoeken…


Opmerkingen

Het dynamic trefwoord declareert een variabele waarvan het type niet bekend is tijdens het compileren. Een dynamic variabele kan elke waarde bevatten en het type waarde kan tijdens runtime veranderen.

Zoals opgemerkt in het boek "Metaprogrammering in .NET" heeft C # geen type back-up voor het dynamic trefwoord:

De functionaliteit die wordt ingeschakeld door het dynamic trefwoord is een slimme set compileracties die CallSite objecten uitzenden en gebruiken in de CallSite van het lokale uitvoeringsbereik. De compiler beheert wat programmeurs waarnemen als dynamische objectverwijzingen via die CallSite instanties. De parameters, retourtypen, velden en eigenschappen die tijdens het compileren dynamisch worden behandeld, kunnen worden gemarkeerd met enkele metagegevens om aan te geven dat ze zijn gegenereerd voor dynamisch gebruik, maar het onderliggende gegevenstype voor hen zal altijd System.Object .

Een dynamische variabele maken

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

Terugkerende dynamiek

using System;

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

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

Een dynamisch object met eigenschappen maken

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

Omgaan met specifieke typen die onbekend zijn tijdens het compileren

De volgende outputequivalentresultaten:

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

Het voordeel van de dynamiek is dat het toevoegen van een nieuw te verwerken type alleen een overbelasting van DebugToStringInternal van het nieuwe type vereist. Het elimineert ook de noodzaak om het ook handmatig naar het type te casten.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow