Для чего 'динамический' тип в C# 4.0, используемом?

C# 4.0 представил новый тип, названный 'динамичным'. Звучит хорошим, но для чего программист использовал бы его?

Существует ли ситуация, где она может спасти положение?

217
задан Peter Mortensen 27 November 2010 в 23:00
поделиться

6 ответов

Ключевое слово dynamic является новым для C # 4.0 и используется, чтобы сообщить компилятору, что тип переменной может измениться или что он неизвестен до времени выполнения. Думайте об этом как о возможности взаимодействовать с объектом без его применения.

dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!

Обратите внимание, что нам не нужно приводить или объявлять cust как тип Customer. Поскольку мы объявили его динамическим, среда выполнения берет на себя управление, а затем выполняет поиск и устанавливает для нас свойство FirstName. Теперь, конечно, когда вы используете динамическую переменную, вы отказываетесь от проверки типа компилятора. Это означает, что вызов cust.MissingMethod () будет компилироваться и не завершится ошибкой до времени выполнения. Результатом этой операции является исключение RuntimeBinderException, поскольку MissingMethod не определен в классе Customer.

В приведенном выше примере показано, как работает динамический при вызове методов и свойств. Еще одна мощная (и потенциально опасная) функция - возможность повторно использовать переменные для разных типов данных. Я уверен, что программисты на Python, Ruby и Perl могут придумать миллион способов воспользоваться этим, но я использую C # так долго, что мне это кажется «неправильным».

dynamic foo = 123;
foo = "bar";

Хорошо, поэтому вы, скорее всего, не будете писать код, подобный приведенному выше, очень часто. Однако могут быть случаи, когда повторное использование переменных может пригодиться или очистить грязный кусок устаревшего кода. Один простой случай, с которым я часто сталкиваюсь, - это постоянное преобразование между десятичным и двойным.

decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");

Вторая строка не компилируется, потому что 2.5 набирается как double, а строка 3 не компилируется, потому что Math.Sqrt ожидает double.Очевидно, все, что вам нужно сделать, это привести и / или изменить тип переменной, но могут быть ситуации, когда имеет смысл использовать динамический.

dynamic foo = GetDecimalValue(); // still returns a decimal
foo = foo / 2.5; // The runtime takes care of this for us
foo = Math.Sqrt(foo); // Again, the DLR works its magic
string bar = foo.ToString("c");

Подробнее: http://www.codeproject.com/KB/cs/CSharp4Features.aspx

177
ответ дан 23 November 2019 в 04:14
поделиться

Он оценивается во время выполнения, поэтому вы можете переключать тип, как в JavaScript, на все, что захотите. Это нормально:

dynamic i = 12;
i = "text";

И поэтому вы можете изменить тип по своему усмотрению. Используйте это как последнее средство; это полезно, но я слышал, что многое происходит за кулисами с точки зрения сгенерированного IL, и это может иметь место в цене за производительность.

0
ответ дан 23 November 2019 в 04:14
поделиться

Это упрощает взаимодействие языков со статической типизацией (CLR) с динамическими языками (python, ruby ​​...), работающими в среде выполнения динамического языка DLR. ), см. MSDN :

Например, вы можете использовать следующий код для увеличения счетчика в XML на C #.

 Scriptobj.SetProperty ("Count", ((int) GetProperty ("Count")) + 1); 
 

Используя DLR, вы можете использовать следующий код вместо {{ 1}} та же операция.

 scriptobj.Count + = 1; 
 

MSDN перечисляет эти преимущества:

  • Упрощает перенос динамических языков в .NET Framework
  • Включает динамические функции на статически типизированных языках
  • Обеспечивает будущее Преимущества DLR и .NET Framework
  • Обеспечивает совместное использование библиотек и объектов
  • Обеспечивает быструю динамическую отправку и вызов

См. MSDN для получения более подробной информации.

11
ответ дан 23 November 2019 в 04:14
поделиться

Ключевое слово dynamic было добавлено вместе со многими другими новыми функциями C # 4.0, чтобы упростить взаимодействие с кодом, который находится в других средах выполнения или поступает из них и имеет другие API.

Возьмем пример.

Если у вас есть 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 с COM API стало проще работать за счет введения:

  1. Необязательных аргументов
  2. Сделать ref необязательным для COM API
  3. Именованных аргументов

Новый синтаксис для вышеуказанного вызов будет выглядеть так:

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 # теперь вставит необходимый код и будет работать с новым классы во время выполнения, чтобы делать почти то же самое, что и раньше, но синтаксис был скрыт от вас, теперь вы можете сосредоточиться на what , а не на how . Андерс Хейлсберг любит говорить, что вы должны использовать разные «заклинания», что является своего рода каламбуром на магии всего этого, где вам обычно нужно махать рукой (-ами) и произносить несколько волшебных слов в правильном порядке. чтобы запустить определенный тип заклинания.В старом API-способе общения с COM-объектами этого было много, вам нужно было перепрыгнуть через множество препятствий, чтобы заставить компилятор скомпилировать код за вас.

В C # до версии 4.0 все ломается еще больше, если вы пытаетесь поговорить с COM-объектом, для которого у вас нет интерфейса или класса, все, что у вас есть, - это ссылка IDispatch .

Если вы не знаете, что это такое, IDispatch в основном является отражением для COM-объектов. С помощью интерфейса IDispatch вы можете спросить объект, «какой номер идентификатора для метода, известного как Save», и создать массивы определенного типа, содержащие значения аргументов, и, наконец, вызвать Invoke в интерфейсе IDispatch для вызова метода, передавая вместе всю информацию, которую вам удалось собрать.

Вышеупомянутый метод сохранения может выглядеть так (это определенно неправильный код):

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, только совсем другое.

А Руби? Еще другой API.

JavaScript? Та же сделка, и для этого другой API.

Ключевое слово dynamic состоит из двух частей:

  1. Ключевое слово new в C #, dynamic
  2. Набор классов времени выполнения, который знает, как работать с различными типами объектов, которые реализуют определенный 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;

и скомпилировать его, он не задумывался как своего рода система типа «волшебство-давайте-выясни-что-вы-имели-во время выполнения». .

Вся цель заключалась в том, чтобы упростить разговор с другими типами объектов.

В Интернете есть множество материалов о ключевых словах, сторонниках, оппонентах, обсуждениях, разглагольствованиях, похвалах и т. Д.

Я предлагаю вам начать со следующих ссылок, а затем погуглить, чтобы узнать больше:

206
ответ дан 23 November 2019 в 04:14
поделиться

COM-взаимодействие. Особенно IUnknown. Он был разработан специально для этого.

3
ответ дан 23 November 2019 в 04:14
поделиться

Он будет в основном использоваться жертвами RAD и Python для снижения качества кода, IntelliSense и обнаружения ошибок во время компиляции.

2
ответ дан 23 November 2019 в 04:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: