Несмотря на то, что 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
для которого предполагается возможность выполнения любых операций.