Шрифт:
Интервал:
Закладка:
dynamic dynamicLocalVar = "Local variable";
int myInt = 10;
if (dynamicParam is int)
{
return dynamicLocalVar;
}
else
{
return myInt;
}
}
}
}
Теперь обращаться к открытым членам можно было бы ожидаемым образом; однако при работе с динамическими методами и свойствами нет полной уверенности в том, каким будет тип данных! По правде говоря, определение VeryDynamicClass может оказаться не особенно полезным в реальном приложении, но оно иллюстрирует область, где допускается применять ключевое слово dynamic.
Ограничения ключевого слова dynamic
Невзирая на то, что с использованием ключевого слова dynamic можно определять разнообразные сущности, с ним связаны некоторые ограничения. Хотя они не настолько впечатляющие, следует помнить, что элементы динамических данных при вызове метода не могут применять лямбда-выражения или анонимные методы С#. Например, показанный ниже код всегда будет давать в результате ошибки, даже если целевой метод на самом деле принимает параметр типа делегата, который в свою очередь принимает значение string и возвращает void:
dynamic a = GetDynamicObject();
// Ошибка! Методы на динамических данных не могут использовать
// лямбда-выражения!
a.Method(arg => Console.WriteLine(arg));
Чтобы обойти упомянутое ограничение, понадобится работать с лежащим в основе делегатом напрямую, используя приемы из главы 12. Еще одно ограничение заключается в том, что динамический элемент данных не может воспринимать расширяющие методы (см. главу 11). К сожалению, сказанное касается также всех расширяющих методов из API-интерфейсов LINQ. Следовательно, переменная, объявленная с ключевым словом dynamic, имеет ограниченное применение в рамках LINQ to Objects и других технологий LINQ:
dynamic a = GetDynamicObject();
// Ошибка! Динамические данные не могут найти расширяющий метод Select()!
var data = from d in a select d;
Практическое использование ключевого слова dynamic
С учетом того, что динамические данные не являются строго типизированными, не проверяются на этапе компиляции, не имеют возможности запускать средство IntelliSense и не могут быть целью запроса LINQ, совершенно корректно предположить, что применение ключевого слова dynamic лишь по причине его существования представляет собой плохую практику программирования.
Тем не менее, в редких обстоятельствах ключевое слово dynamic может радикально сократить объем вводимого вручную кода. В частности, при построении приложения .NET Core, в котором интенсивно используется позднее связывание (через рефлексию), ключевое слово dynamic может сэкономить время на наборе кода. Аналогично при разработке приложения .NET Core, которое должно взаимодействовать с унаследованными библиотеками СОМ (вроде тех, что входят в состав продуктов Microsoft Office), за счет использования ключевого слова dynamic можно значительно упростить кодовую базу. В качестве финального примера можно привести веб-приложения, построенные с применением ASP.NET Core: они часто используют тип ViewBag, к которому также допускается производить доступ в упрощенной манере с помощью ключевого слова dynamic.
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})На заметку! Взаимодействие с СОМ является строго парадигмой Windows и исключает межплатформенные возможности из вашего приложения.
Как с любым "сокращением", прежде чем его использовать, необходимо взвесить все "за" и "против". Применение ключевого слова dynamic — компромисс между краткостью кода и безопасностью к типам. В то время как C# в своей основе является строго типизированным языком, динамическое поведение можно задействовать (или нет) от вызова к вызову. Всегда помните, что использовать ключевое слово dynamic необязательно. Тот же самый конечный результат можно получить, написав альтернативный код вручную (правда, обычно намного большего объема).
Роль исполняющей среды динамического языка
Теперь, когда вы лучше понимаете сущность "динамических данных", давайте посмотрим, как их обрабатывать. Начиная с версии .NET 4.0, общеязыковая исполняющая среда (Common Language Runtime — CLR) получила дополняющую среду времени выполнения, которая называется исполняющей средой динамического языка (Dynamic Language Runtime — DLR). Концепция "динамической исполняющей среды" определенно не нова. На самом деле ее много лет используют такие языки программирования, как JavaScript, LISP, Ruby и Python. Выражаясь кратко, динамическая исполняющая среда предоставляет динамическим языкам возможность обнаруживать типы полностью во время выполнения без каких-либо проверок на этапе компиляции.
На заметку! Хотя большая часть функциональных средств среды DLR была перенесена в .NET Core (начиная с версии 3.0), паритет в плане функциональности между DLR в .NET Core 5 и .NET 4.8 так и не был достигнут.
Если у вас есть опыт работы со строго типизированными языками (включая C# без динамических типов), тогда идея такой исполняющей среды может показаться неподходящей. В конце концов, вы обычно хотите выявлять ошибки на этапе компиляции, а не во время выполнения, когда только возможно. Тем не менее, динамические языки и исполняющие среды предлагают ряд интересных средств, включая перечисленные ниже.
• Чрезвычайно гибкая кодовая база. Можно проводить рефакторинг кода, не внося многочисленных изменений в типы данных.
• Простой способ взаимодействия с разнообразными типами объектов, которые построены на разных платформах и языках программирования.
• Способ добавления или удаления членов типа в памяти во время выполнения.
Одна из задач среды DLR заключается в том, чтобы позволить различным динамическим языкам работать с исполняющей средой .NET Core и предоставлять им возможность взаимодействия с другим кодом .NET Core. Двумя популярными динамическими языками, которые используют DLR, являются IronPython и IronRuby. Указанные языки находятся в "динамической вселенной", где типы определяются целиком во время выполнения. К тому же данные языки имеют доступ ко всему богатству библиотек базовых классов .NET Core. А еще лучше то, что благодаря наличию ключевого слова dynamic их кодовые базы могут взаимодействовать с языком C# (и наоборот).
- Понимание SQL - Мартин Грубер - Базы данных