Это полезно при работе с COM или динамически типизированными языками. Например, если вы используете lua или python для написания скриптов на вашем языке, очень удобно просто вызывать код скриптинга, как если бы это был обычный код.
Ключевое слово 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 compilestring 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 magicstring bar = foo.ToString("c");
Лично мне не нравится мысль об использовании dynamicin c # для решения проблем, которые могут быть решены (возможно, даже лучше) стандартными функциями c # и статической типизацией, или, самое большее, с помощью inference типа ( var). dynamicследует использовать только когда речь идет о проблемах взаимодействия с DLR. Если вы пишете код на статическом типизированном языке, таком как c # is, то делайте это и не эмулируйте динамический язык. Это просто безобразно.
Филипп Добмайер
40
Если вы интенсивно используете dynamicпеременные в своем коде там, где они вам не нужны (как в вашем примере с квадратным корнем), вы прекращаете чистую проверку ошибок времени компиляции; вместо этого вы теперь получаете возможные ошибки во время выполнения.
Филипп Добмайер
33
В основном нормально, но пара мелких ошибок. Во-первых, неверно говорить, что динамический означает, что тип переменной может измениться. Рассматриваемая переменная имеет тип «динамический» (с точки зрения языка C #; с точки зрения CLR переменная имеет тип объекта). Тип переменной никогда не меняется. Тип времени выполнения значения переменной может быть любым типом, совместимым с типом переменной. (Или в случае ссылочных типов это может быть нулевым.)
Эрик Липперт
15
Что касается вашего второго замечания: в C # уже есть функция «создать переменную, в которую вы можете поместить что угодно» - вы всегда можете создать переменную типа object. Интересная вещь о динамике - это то, что вы указали в первом абзаце: динамический почти идентичен объекту, за исключением того, что семантический анализ откладывается до времени выполнения, а семантический анализ выполняется для типа выражения выражения во время выполнения. (В основном. Есть некоторые исключения.)
Эрик Липперт
18
Я потратил на это отрицательное мнение, главным образом потому, что он косвенно выступает за использование ключевого слова для общего пользования. У него есть целенаправленная цель (она отлично описана в ответе Ласса), и хотя этот ответ технически правильный, он, вероятно, приведет разработчиков в заблуждение.
Восьмибитный Гуру
211
dynamicКлючевое слово добавлено, вместе со многими другими новыми функциями C # 4.0, чтобы сделать его проще говорить с кодом , который живет в или приходит от других сред исполнения, который имеет различные интерфейсы.
Возьми пример.
Если у вас есть COM-объект, такой как Word.Applicationобъект, и вы хотите открыть документ, метод для этого содержит не менее 15 параметров, большинство из которых являются необязательными.
Чтобы вызвать этот метод, вам нужно что-то вроде этого (я упрощаю, это не настоящий код):
Обратите внимание на все эти аргументы? Вы должны передать их, так как C # до версии 4.0 не имел понятия необязательных аргументов. В C # 4.0 с COM API стало проще работать, введя:
Видите, насколько легче это выглядит, насколько более читабельным это становится?
Давайте разберем это на части:
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 может выглядеть следующим образом (это определенно неправильный код):
в основном просто C # догоняет VB с точки зрения выразительности, но делает это правильно, делая его расширяемым, а не только для COM. Конечно, это также доступно для VB.NET или любого другого языка, построенного поверх среды выполнения .NET.
Вы можете найти больше информации об IDispatchинтерфейсе в Википедии: IDispatch если вы хотите узнать больше об этом. Это действительно ужасные вещи.
Однако, что если вы хотите поговорить с объектом Python? Для этого есть другой API, чем тот, который используется для COM-объектов, и, поскольку объекты Python также являются динамическими по своей природе, вам нужно прибегнуть к магии отражения, чтобы найти правильные методы для вызова, их параметры и т. Д., Но не .NET отражение, что-то написанное для Python, в значительной степени похожее на приведенный выше код IDispatch, просто совсем другое.
А для Руби? Другой API все еще.
JavaScript? То же самое, другой API для этого тоже.
Ключевое слово dynamic состоит из двух вещей:
Новое ключевое слово в 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 для получения дополнительной информации:
Я не согласен с ним, но это вопрос мнения, а не факта. «Строго типизированный» для меня означает, что компилятор знает, во время компиляции, какой тип используется, и, таким образом, обеспечивает соблюдение правил, установленных для этих типов. Тот факт, что вы можете выбрать динамический тип, который откладывает проверку правил и привязку к среде выполнения, для меня не означает, что язык слабо типизирован. Я обычно не сравниваю строго типизированный со слабо типизированным, однако я обычно сравниваю его с динамически типизированным, например, с такими языками, как Python, где все является уткой, пока не лает.
Лассе В. Карлсен
Какой смысл этого ответа? Половина этого относится к необязательным параметрам и интерфейсу IDispatch.
Xam
Вот почему dynamicбыло добавлено, чтобы поддержать другие экосистемы в том, как может быть выполнен вызов метода, подобного отражению, а также обеспечить своего рода подход черного ящика к структурам данных с документированным способом достижения этого.
Лассе В. Карлсен
29
Я удивлен, что никто не упомянул многократную рассылку . Обычный способ обойти это через шаблон посетителя, и это не всегда возможно, так что вы в конечном итоге с накоплениемis чеки .
Итак, вот реальный пример применения моего собственного приложения. Вместо того, чтобы делать:
publicstaticMapDtoBaseCreateDto(ChartItem item){if(item isElevationPoint)returnCreateDtoImpl((ElevationPoint)item);if(item isMapPoint)returnCreateDtoImpl((MapPoint)item);if(item isMapPolyline)returnCreateDtoImpl((MapPolyline)item);//other subtypes followthrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}
Вы делаете:
publicstaticMapDtoBaseCreateDto(ChartItem item){returnCreateDtoImpl(item asdynamic);}privatestaticMapDtoBaseCreateDtoImpl(ChartItem item){thrownewObjectNotFoundException("Counld not find suitable DTO for "+ item.GetType());}privatestaticMapDtoBaseCreateDtoImpl(MapPoint item){returnnewMapPointDto(item);}privatestaticMapDtoBaseCreateDtoImpl(ElevationPoint item){returnnewElevationDto(item);}
Обратите внимание, что в первом случае ElevationPointэто подкласс класса, MapPointи если он не размещен доMapPoint этого, он никогда не будет достигнут. В случае с динамическим это не так, так как будет вызван ближайший метод сопоставления.
Как можно догадаться из кода, эта функция пригодилась, когда я выполнял перевод объектов ChartItem в их сериализуемые версии. Я не хотел загрязнять свой код посетителями и не хотел также загрязнять свои ChartItemобъекты бесполезными специфическими атрибутами сериализации.
Не знал об этом случае использования. Хотя немного в лучшем случае. Это отбросит любой статический анализатор.
Кугель
2
@ Кугель, это правда, но я бы не назвал это хаком . Статический анализ - это хорошо, но я бы не позволил ему помешать изящному решению, где есть альтернативы: нарушение принципа открытого-закрытого типа (шаблон посетителя) или повышенная цикломатическая сложность, когда страшно isсложены один поверх другого.
Стелиос Адамантидис
4
Ну, у вас есть возможность сопоставления с шаблоном в C # 7, нет?
Кугель
2
Что ж, операторы намного дешевле (без двойного приведения), и вы получаете статический анализ ;-) и производительность.
Кугель
@idbrii, пожалуйста, не меняй мои ответы. Не стесняйтесь оставлять комментарии, и я уточню (при необходимости), как я все еще активен в этом сообществе. Кроме того, пожалуйста, не используйте magic; нет такой вещи как магия.
Стелиос Адамантидис
11
Для статических типизированных языков (CLR) легче взаимодействовать с динамическими (python, ruby ...), работающими на DLR (динамическая среда исполнения языка), см. MSDN :
Например, вы можете использовать следующий код для увеличения счетчика в XML в C #.
И изменение виртуальной машины, необходимой для динамического, на самом деле делает динамические языки проще
Dykam
2
@Dykam: нет никаких изменений в виртуальной машине. DLR прекрасно работает вплоть до .NET 2.0.
Йорг Миттаг,
@ Йорг, да, есть изменения. DLR частично переписан, потому что теперь виртуальная машина имеет встроенную поддержку динамического разрешения.
Dykam
Я был слишком оптимистичен, исследования показали, что изменения не такие большие.
Dykam
4
Пример использования:
Вы потребляете много классов, у которых есть общее свойство CreationDate:
publicclassContact{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassCompany{// some propertiespublicDateTimeCreationDate{get;set;}}publicclassOpportunity{// some propertiespublicDateTimeCreationDate{get;set;}}
Если вы напишите метод commun, который извлекает значение свойства 'CreationDate', вам придется использовать отражение:
Циничный ответ, но легко слишком верный. Я видел, как это делается просто для того, чтобы избежать объявления структур, в результате чего код работает, если все хорошо, но создает непредсказуемые последствия для своего стека, как только вы перемещаете его сыр.
AnthonyVO
Да, вы увидите эту классическую угловую раскрой со множеством других языковых функций. Неудивительно, что вы также увидите это здесь.
Hawkeye4040
1
Он оценивает во время выполнения, так что вы можете переключать тип, как вы можете в JavaScript, на что угодно. Это законно
dynamic i =12;
i ="text";
И поэтому вы можете изменить тип, как вам нужно. Используйте это как последнее средство; это полезно, но я слышал, что многое происходит за кулисами с точки зрения генерируемого ИЛ, и это может стоить производительности.
Я бы не решился сказать, что это «законно». Он наверняка скомпилируется, поэтому он является «законным кодом» в том смысле, что компилятор теперь скомпилирует его, а среда выполнения запустит его. Но я бы никогда не хотел видеть этот конкретный кусок кода (или что-то похожее на него) в каком-либо коде, который я поддерживаю, или это было бы почти увольнением.
Лассе В. Карлсен
6
Конечно, но это было бы "законно" с "объектом" вместо "динамического". Вы не показали ничего интересного о динамике здесь.
Эрик Липперт
Для объекта вам придется привести его к соответствующему типу, чтобы фактически вызвать любой из его методов ... вы потеряете сигнатуру; Вы можете сделать так, чтобы ваш код вызывал любой метод без ошибок компиляции, и он выдает ошибки во время выполнения. Спешил набрать, извините, что не уточнил. И @Lasse, я бы согласился, и я, вероятно, не буду часто использовать динамику.
Брайан Майнс
1
В крайнем случае вариант использования не объяснен
denfromufa
1
Лучший вариант использования переменных типа «динамический» для меня был, когда недавно я писал слой доступа к данным в ADO.NET ( с использованием SQLDataReader ), а код вызывал уже написанные унаследованные хранимые процедуры. Существуют сотни таких устаревших хранимых процедур, содержащих большую часть бизнес-логики. Мой уровень доступа к данным должен был возвращать какие-то структурированные данные на уровень бизнес-логики, основанный на C #, для выполнения некоторых манипуляций ( хотя их почти нет ). Каждая хранимая процедура возвращает различный набор данных ( столбцы таблицы ). Поэтому вместо того, чтобы создавать десятки классов или структур для хранения возвращаемых данных и передачи их в BLL, я написал приведенный ниже код, который выглядит довольно элегантно и аккуратно.
publicstaticdynamicGetSomeData(ParameterDTO dto){dynamic result =null;stringSPName="a_legacy_stored_procedure";
using (SqlConnection connection =newSqlConnection(DataConnection.ConnectionString)){SqlCommand command =newSqlCommand(SPName, connection);
command.CommandType=System.Data.CommandType.StoredProcedure;
command.Parameters.Add(newSqlParameter("@empid", dto.EmpID));
command.Parameters.Add(newSqlParameter("@deptid", dto.DeptID));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()){while(reader.Read()){dynamic row =newExpandoObject();
row.EmpName= reader["EmpFullName"].ToString();
row.DeptName= reader["DeptName"].ToString();
row.AnotherColumn= reader["AnotherColumn"].ToString();
result = row;}}}return result;}
Вы можете вызывать динамические языки, такие как CPython, используя pythonnet:
dynamic np = Py.Import("numpy")
Вы можете использовать дженерики dynamicпри применении к ним числовых операторов. Это обеспечивает безопасность типов и позволяет избежать ограничений генериков. Это по сути * утка набирает:
Другой вариант использования для dynamicнабора текста - для виртуальных методов, которые сталкиваются с проблемой ковариации или контравариантности. Одним из таких примеров является печально известный Cloneметод, который возвращает объект того же типа, что и объект, к которому он вызывается. Эта проблема не полностью решена динамическим возвратом, потому что она обходит статическую проверку типов, но, по крайней мере, вам не нужно все время использовать некрасивые приведения, как при использовании plain object. Иначе говоря, приведения становятся неявными.
publicclass A
{// attributes and constructor herepublicvirtualdynamicClone(){var clone =new A();// Do more cloning stuff herereturn clone;}}publicclass B : A
{// more attributes and constructor herepublicoverridedynamicClone(){var clone =new B();// Do more cloning stuff herereturn clone;}}publicclassProgram{publicstaticvoidMain(){
A a =new A().Clone();// No cast needed here
B b =new B().Clone();// and here// do more stuff with a and b}}
Ответы:
Ключевое слово dynamic является новым для C # 4.0 и используется, чтобы сообщить компилятору, что тип переменной может измениться или что она неизвестна до времени выполнения. Думайте об этом как о возможности взаимодействовать с Объектом без необходимости его наложения.
Обратите внимание, что нам не нужно ни приводить, ни объявлять cust как тип Customer. Поскольку мы объявили его динамическим, среда выполнения вступает во владение, а затем ищет и задает нам свойство FirstName. Теперь, конечно, когда вы используете динамическую переменную, вы отказываетесь от проверки типа компилятора. Это означает, что вызов cust.MissingMethod () будет скомпилирован и не завершится с ошибкой до времени выполнения. Результатом этой операции является исключение RuntimeBinderException, поскольку MissingMethod не определен в классе Customer.
В приведенном выше примере показано, как работает динамический при вызове методов и свойств. Еще одна мощная (и потенциально опасная) функция - возможность многократного использования переменных для разных типов данных. Я уверен, что программисты на Python, Ruby и Perl могут придумать миллион способов воспользоваться этим, но я использовал C # так долго, что мне это кажется «неправильным».
ОК, так что вы, скорее всего, не будете часто писать код, подобный приведенному выше. Однако могут быть случаи, когда повторное использование переменных может пригодиться или очистить грязный фрагмент устаревшего кода. Один простой случай, с которым я часто сталкиваюсь, это постоянное приведение между десятичным и двойным.
Вторая строка не компилируется, потому что 2.5 имеет тип double, а строка 3 не компилируется, потому что Math.Sqrt ожидает double. Очевидно, что все, что вам нужно сделать, это привести и / или изменить тип переменной, но могут быть ситуации, когда имеет смысл использовать динамический.
Подробнее читайте: http://www.codeproject.com/KB/cs/CSharp4Features.aspx
источник
dynamic
in c # для решения проблем, которые могут быть решены (возможно, даже лучше) стандартными функциями c # и статической типизацией, или, самое большее, с помощью inference типа (var
).dynamic
следует использовать только когда речь идет о проблемах взаимодействия с DLR. Если вы пишете код на статическом типизированном языке, таком как c # is, то делайте это и не эмулируйте динамический язык. Это просто безобразно.dynamic
переменные в своем коде там, где они вам не нужны (как в вашем примере с квадратным корнем), вы прекращаете чистую проверку ошибок времени компиляции; вместо этого вы теперь получаете возможные ошибки во время выполнения.dynamic
Ключевое слово добавлено, вместе со многими другими новыми функциями C # 4.0, чтобы сделать его проще говорить с кодом , который живет в или приходит от других сред исполнения, который имеет различные интерфейсы.Возьми пример.
Если у вас есть COM-объект, такой как
Word.Application
объект, и вы хотите открыть документ, метод для этого содержит не менее 15 параметров, большинство из которых являются необязательными.Чтобы вызвать этот метод, вам нужно что-то вроде этого (я упрощаю, это не настоящий код):
Обратите внимание на все эти аргументы? Вы должны передать их, так как C # до версии 4.0 не имел понятия необязательных аргументов. В C # 4.0 с COM API стало проще работать, введя:
ref
необязательным для COM APIНовый синтаксис для вышеуказанного вызова будет:
Видите, насколько легче это выглядит, насколько более читабельным это становится?
Давайте разберем это на части:
Волшебство в том, что компилятор C # теперь будет вводить необходимый код и работать с новыми классами во время выполнения, чтобы сделать почти то же самое, что вы делали раньше, но синтаксис был скрыт от вас, теперь вы можете сосредоточиться на что , и не так много о том, как . Андерс Хейлсберг любит говорить, что вы должны вызывать различные «заклинания», что является своего рода каламбуром в магии всего этого, когда вы обычно должны махать рукой (руками) и произносить магические слова в правильном порядке. чтобы получить заклинание определенного типа. Старый API-способ общения с COM-объектами заключался в том, что вам нужно было прыгать через множество циклов, чтобы уговорить компилятор скомпилировать код для вас.
В C # до версии 4.0 дела обстоят хуже, даже если вы попытаетесь поговорить с COM-объектом, для которого у вас нет интерфейса или класса, все, что у вас есть, - это
IDispatch
ссылка.Если вы не знаете, что это такое,
IDispatch
это в основном отражение для объектов COM. С помощьюIDispatch
интерфейса вы можете задать объекту «что такое номер идентификатора для метода, известного как Save», и создать массивы определенного типа, содержащие значения аргументов, и, наконец, вызватьInvoke
методIDispatch
интерфейса для вызова метода, передав все информация, которую вам удалось собрать вместе.Приведенный выше метод Save может выглядеть следующим образом (это определенно неправильный код):
Все это только для открытия документа.
VB имел необязательные аргументы и поддержку большей части этого из коробки давно, поэтому этот код C #:
в основном просто C # догоняет VB с точки зрения выразительности, но делает это правильно, делая его расширяемым, а не только для COM. Конечно, это также доступно для VB.NET или любого другого языка, построенного поверх среды выполнения .NET.
Вы можете найти больше информации об
IDispatch
интерфейсе в Википедии: IDispatch если вы хотите узнать больше об этом. Это действительно ужасные вещи.Однако, что если вы хотите поговорить с объектом Python? Для этого есть другой API, чем тот, который используется для COM-объектов, и, поскольку объекты Python также являются динамическими по своей природе, вам нужно прибегнуть к магии отражения, чтобы найти правильные методы для вызова, их параметры и т. Д., Но не .NET отражение, что-то написанное для Python, в значительной степени похожее на приведенный выше код IDispatch, просто совсем другое.
А для Руби? Другой API все еще.
JavaScript? То же самое, другой API для этого тоже.
Ключевое слово dynamic состоит из двух вещей:
dynamic
dynamic
требуется для ключевого слова, и сопоставляют вызовы с правильным способом выполнения действий. API даже задокументирован, поэтому, если у вас есть объекты, полученные из незавершенной среды выполнения, вы можете добавить их.Однако
dynamic
ключевое слово не предназначено для замены какого-либо существующего кода .NET. Конечно, вы можете сделать это, но он не был добавлен по этой причине, и авторы языка программирования C # с Андерсом Хейлсбергом впереди, были непреклонны в том, что они по-прежнему рассматривают C # как строго типизированный язык, и не будут жертвовать этот принцип.Это означает, что хотя вы можете написать код так:
и чтобы он был скомпилирован, он не был задуман как своего рода система типа «давай выясним, что ты имел в виду во время выполнения».
Целью было облегчить общение с другими типами предметов.
В Интернете много материала о ключевых словах, сторонниках, противниках, обсуждениях, недовольстве, похвале и т. Д.
Я предлагаю вам начать со следующих ссылок, а затем Google для получения дополнительной информации:
источник
dynamic
было добавлено, чтобы поддержать другие экосистемы в том, как может быть выполнен вызов метода, подобного отражению, а также обеспечить своего рода подход черного ящика к структурам данных с документированным способом достижения этого.Я удивлен, что никто не упомянул многократную рассылку . Обычный способ обойти это через шаблон посетителя, и это не всегда возможно, так что вы в конечном итоге с накоплением
is
чеки .Итак, вот реальный пример применения моего собственного приложения. Вместо того, чтобы делать:
Вы делаете:
Обратите внимание, что в первом случае
ElevationPoint
это подкласс класса,MapPoint
и если он не размещен доMapPoint
этого, он никогда не будет достигнут. В случае с динамическим это не так, так как будет вызван ближайший метод сопоставления.Как можно догадаться из кода, эта функция пригодилась, когда я выполнял перевод объектов ChartItem в их сериализуемые версии. Я не хотел загрязнять свой код посетителями и не хотел также загрязнять свои
ChartItem
объекты бесполезными специфическими атрибутами сериализации.источник
is
сложены один поверх другого.magic
; нет такой вещи как магия.Для статических типизированных языков (CLR) легче взаимодействовать с динамическими (python, ruby ...), работающими на DLR (динамическая среда исполнения языка), см. MSDN :
MSDN перечисляет эти преимущества:
Смотрите MSDN для более подробной информации.
источник
Пример использования:
Вы потребляете много классов, у которых есть общее свойство CreationDate:
Если вы напишите метод commun, который извлекает значение свойства 'CreationDate', вам придется использовать отражение:
С «динамической» концепцией ваш код выглядит намного элегантнее:
источник
COM-взаимодействие Особенно неизвестно. Он был разработан специально для этого.
источник
Он будет в основном использоваться жертвами RAD и Python для разрушения качества кода, IntelliSense и обнаружения ошибок времени компиляции.
источник
Он оценивает во время выполнения, так что вы можете переключать тип, как вы можете в JavaScript, на что угодно. Это законно
И поэтому вы можете изменить тип, как вам нужно. Используйте это как последнее средство; это полезно, но я слышал, что многое происходит за кулисами с точки зрения генерируемого ИЛ, и это может стоить производительности.
источник
Лучший вариант использования переменных типа «динамический» для меня был, когда недавно я писал слой доступа к данным в ADO.NET ( с использованием SQLDataReader ), а код вызывал уже написанные унаследованные хранимые процедуры. Существуют сотни таких устаревших хранимых процедур, содержащих большую часть бизнес-логики. Мой уровень доступа к данным должен был возвращать какие-то структурированные данные на уровень бизнес-логики, основанный на C #, для выполнения некоторых манипуляций ( хотя их почти нет ). Каждая хранимая процедура возвращает различный набор данных ( столбцы таблицы ). Поэтому вместо того, чтобы создавать десятки классов или структур для хранения возвращаемых данных и передачи их в BLL, я написал приведенный ниже код, который выглядит довольно элегантно и аккуратно.
источник
dynamic np = Py.Import("numpy")
dynamic
при применении к ним числовых операторов. Это обеспечивает безопасность типов и позволяет избежать ограничений генериков. Это по сути * утка набирает:T y = x * (dynamic)x
, гдеtypeof(x) is T
источник
Другой вариант использования для
dynamic
набора текста - для виртуальных методов, которые сталкиваются с проблемой ковариации или контравариантности. Одним из таких примеров является печально известныйClone
метод, который возвращает объект того же типа, что и объект, к которому он вызывается. Эта проблема не полностью решена динамическим возвратом, потому что она обходит статическую проверку типов, но, по крайней мере, вам не нужно все время использовать некрасивые приведения, как при использовании plainobject
. Иначе говоря, приведения становятся неявными.источник