C# Language
Динамический тип
Поиск…
замечания
dynamic
ключевое слово объявляет переменную, тип которой неизвестен во время компиляции. dynamic
переменная может содержать любое значение, а тип значения может изменяться во время выполнения.
Как отмечено в книге «Метапрограммирование в .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 нового типа. Также устраняет необходимость вручную отбрасывать его на тип.