Несмотря на то, что C# — это язык со статической типизацией, начиная с .NET 4, благодаря появлению в составе .NET среды Dynamic Language Runtime (DLR), в язык были добавлены некоторые возможности, присущие языкам с динамической типизацией, таких как JavaScript, IronPython и т.д.
Ключевое слово dynamic
В динамических языках тип объекта может определяться во время выполнения, тогда как в языках со статической типизацией типы объектов следует указывать во время разработки. Это означает, что при программировании на C# мы не можем написать вот такой код:
int i = 1; i = "Hello world!";
так как для переменной i был указан тип int, мы не можем сменить этот тип в дальнейшем, даже, если попробуем объявить переменную так:
var i = 1; i = "Hello world!";
тип переменной будет выведен из выражения справа (о неявно типизированных переменных можно прочитать здесь). При этом, используя ключевое слово dynamic мы можем обойти типа следующий код скомпилируется и будет работать:
dynamic i = 1; i = "Hello world!";
На первый взгляд может показаться, что использование dynamic ломает одну из ключевых концепций языка C#, а именно — нарушаются принципы статической типизации. На самом деле это не так. Тип dynamic является статическим типом, но, при этом, объект типа dynamic обходит проверку статического типа и, в большинстве случаев, работает как тип object.
dynamic, поддерживает любые операции.Так как объект типа dynamic обходит проверку статического типа, то следующий код также будет успешно скомпилирован и выполнен:
dynamic i = 12345; dynamic s = "Hello world"; dynamic n = s + i; Console.WriteLine(n);
Тип dynamic также может быть применен к результату, возвращаемого значения. Например:
static dynamic DynamicMethod(int a, int b, bool stringResult)
{
if (stringResult)
{
return $"Сумма двух чисел равна {a + b}";
}
else
{
return a + b;
}
}
static void Main(string[] args)
{
int sum = DynamicMethod(1, 2, false);
string strSum = DynamicMethod(1, 2, true);
Console.WriteLine(sum);
Console.WriteLine(strSum);
}
В результате получим следующий вывод в консоль:
Сумма двух чисел равна 3
С одной стороны, тип dynamic позволяет не задумываться о том, из какого источника поступили данные, какого они типа, какие операции поддерживают и так далее. При этом, использование этого типа сопряжено с некоторыми проблемами. Так, например, при использовании dynamic следует быть наиболее внимательным, так как на dynamic не распространяется действие IntelliSense. Например, следующий код IDE пропустит и скомпилирует, однако, на этапе выполнения возникнет ошибка:
dynamic value = 55; string type = value.getType().Name;
Ошибка будет следующая:
Во время выполнения был выведен тип переменной value — int, однако, у этого типа не обнаружен метод getType(). Правильный код выглядел бы так:
string type = value.GetType().Name;
Где использование dynamic в C# необходимо?
Основное назначение среды DLR в .NET определено следующим образом:
Поэтому, если у вас нет необходимости в таком взаимодействии, например, с IronPython, то, чисто технически, dynamic можно не использовать совсем. При желании (и наличии большого количества свободного времени) любой код, использующий тип dynamic можно переписать в привычном статическом виде.
При этом, в некоторых случаях, тип dynamic позволяет сделать наш код более лаконичным и читабельным. С динамическими типами мы сталкиваемся, например, при взаимодействии с COM. Та же работа с Excel в C# предполагает использование dynamic практически повсеместно.
Итого
Среда Dynamic Language Runtime добавляет в C# некоторое динамическое поведение в C#, позволяя создавать и использовать динамические объекты и методы. Ключевым, при этом, является тип dynamic, являющийся, по сути статическим типом, который обходит проверки статического типа и, в большинстве случаев. работает как обычный статический тип object для которого предполагается возможность выполнения любых операций.