Szukaj…


Uwagi

dynamic słowo kluczowe deklaruje zmienną, której typ nie jest znany w czasie kompilacji. Zmienna dynamic może zawierać dowolną wartość, a typ wartości może się zmieniać w czasie wykonywania.

Jak zauważono w książce „Metaprogramowanie w .NET”, C # nie ma typu kopii zapasowej dla słowa kluczowego dynamic :

Funkcjonalność włączana przez słowo kluczowe dynamic to sprytny zestaw działań kompilatora, które emitują i wykorzystują obiekty CallSite w kontenerze serwisu o lokalnym zasięgu wykonania. Kompilator zarządza tym, co programiści postrzegają jako odwołania do obiektów dynamicznych za pośrednictwem tych instancji CallSite . Parametry, typy zwracanych danych, pola i właściwości, które są traktowane dynamicznie w czasie kompilacji, mogą być oznaczone niektórymi metadanymi wskazującymi, że zostały wygenerowane do użytku dynamicznego, ale podstawowym typem danych dla nich zawsze będzie System.Object .

Tworzenie zmiennej dynamicznej

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

Zwrot dynamiczny

using System;

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

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

Tworzenie obiektu dynamicznego o właściwościach

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

Obsługa określonych typów nieznanych w czasie kompilacji

Następujące wyniki równoważne z wynikami:

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

Zaletą dynamiki jest to, że dodanie nowego typu do obsługi wymaga jedynie dodania przeciążenia DebugToStringInternal nowego typu. Eliminuje również konieczność ręcznego rzucania go na ten typ.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow