C# Language
Typ dynamiczny
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ą obiektyCallSite
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 instancjiCallSite
. 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ędzieSystem.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.