Ключевое слово dynamic
было добавлено вместе со многими другими новыми функциями C # 4.0, чтобы упростить общение с кодом, который существует в других средах выполнения или происходит из него, с другими API.
Takeпример.
Если у вас есть COM-объект, такой как объект Word.Application
, и вы хотите открыть документ, метод для этого состоит не менее чем из 15 параметров, большинство из которых являются необязательными.
Чтобы вызвать этот метод, вам нужно что-то вроде этого (я упрощаю, это не настоящий код):
object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing);
Обратите внимание на все эти аргументы?Вы должны передать их, так как C # до версии 4.0 не имел понятия необязательных аргументов.В C # 4.0 с API-интерфейсами COM стало проще работать, введя:
- Необязательные аргументы
- Включение
ref
необязательно для COM-интерфейсов - Именованные аргументы
Новый синтаксис для вышеуказанного вызова будет выглядеть следующим образом:
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
Посмотрите, насколько проще это выглядит, насколько более читабельным оно становится?
Давайте разберемся с этимобособленно:
named argument, can skip the rest
|
v
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
^ ^
| |
notice no ref keyword, can pass
actual parameter values instead
Волшебство заключается в том, что компилятор C # теперь будет вводить необходимый код и работать с новыми классами во время выполнения, чтобы сделать почти то же самое, что вы делали раньше, но синтаксис имеетбыло скрыто от вас, теперь вы можете сосредоточиться на что , а не столько на как .Андерс Хейлсберг любит говорить, что вы должны вызывать различные «заклинания», что является своего рода каламбуром в магии всего этого, когда вы обычно должны махать руками (руками) и произносить магические слова в правильном порядке.чтобы получить заклинание определенного типа.Старый API-способ общения с COM-объектами заключался в том, что вам нужно было перепрыгивать через множество обручей, чтобы уговорить компилятор скомпилировать код для вас.
В C # до версии все сломалось4.0 даже больше, если вы попытаетесь поговорить с COM-объектом, для которого у вас нет интерфейса или класса, все, что у вас есть, - это IDispatch
ссылка.
Если вы не знаете, что это такое,IDispatch
является в основном отражением для объектов COM.С интерфейсом IDispatch
вы можете спросить у объекта «каков номер идентификатора для метода, известного как Save», и создать массивы определенного типа, содержащие значения аргументов, и, наконец, вызвать метод Invoke
для IDispatch
интерфейс для вызова метода, передавая всю информацию, которую вам удалось собрать вместе.
Вышеупомянутый метод Save может выглядеть следующим образом (это определенно неправильный код):
string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);
Все это для простого открытия документа.
VB уже давно имел необязательные аргументы и поддержку большей части этого из коробки, поэтому код C #:
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
в основном просто C # догоняет VB с точки зрения выразительности, но делает это правильно, делая его расширяемым, а не только для COM.Конечно, это также доступно для VB.NET или любого другого языка, построенного поверх среды выполнения .NET.
Более подробную информацию об интерфейсе IDispatch
можно найти в Википедия: IDispatch если вы хотите узнать больше об этом.Это действительно ужасно.
Однако, что если вы захотите поговорить с объектом Python?Для этого есть другой API, чем тот, который используется для COM-объектов, и, поскольку объекты Python также являются динамическими по своей природе, вам нужно прибегнуть к магии отражения, чтобы найти правильные методы для вызова, их параметры и т. Д., Но не .NETотражение, что-то написанное для Python, в значительной степени похожее на приведенный выше код IDispatch, просто совсем другое.
А для Ruby?Другой API все еще.
JavaScript?То же самое, другой API для этого тоже.
Динамическое ключевое слово состоит из двух вещей:
- Новое ключевое слово в C #,
dynamic
- Набор классов времени выполнения, которые знают, как обращаться с различными типами объектов, которые реализуют определенный API, который требуется для ключевого слова
dynamic
, и сопоставляют вызовы с правильным способом выполнения действий. API даже задокументирован, поэтому, если у вас есть объекты, которые не были рассмотрены во время выполнения, вы можете добавить его.
Однако ключевое слово dynamic
не предназначено для замены любого существующего кода .NET. Конечно, вы можете сделать это, но он не был добавлен по этой причине, и авторы языка программирования C # с Андерсом Хейлсбергом впереди были наиболее непреклонны в том, что они по-прежнему считают C # строго типизированным. язык, и не будет жертвовать этим принципом.
Это означает, что, хотя вы можете написать код, подобный этому:
dynamic x = 10;
dynamic y = 3.14;
dynamic z = "test";
dynamic k = true;
dynamic l = x + y * z - k;
и скомпилируйте его, это не было задумано как система типа "магия позволяет выяснить, что вы имели в виду во время выполнения".
Целью было облегчить общение с другими типами объектов.
В интернете много материалов о ключевых словах, сторонниках, противниках, обсуждениях, недовольстве, похвале и т. Д.
Я предлагаю вам начать со следующих ссылок, а затем Google для получения дополнительной информации: