Динамический язык. Время выполнения против отражения

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

Ниже приведены плюсы, которые я могу найти в отношении динамического ключевого слова:

  • Читаемый\Поддерживаемый код.
  • Меньше строк кода.

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

  • Влияет на производительность приложений.
  • Динамическое ключевое слово является внутренней оболочкой Reflection.
  • Динамическая типизация может превратиться в рассадник трудно обнаруживаемых ошибок.
  • Влияет на совместимость с предыдущими версиями .NET.

Пожалуйста, помогите мне понять, разумны ли плюсы и минусы, с которыми я столкнулся, или нет?


person AbrahamJP    schedule 10.01.2011    source источник
comment
Вам нужно сделать частное отражение?   -  person Eric Lippert    schedule 10.01.2011
comment
Нет, мне не нужны частные размышления. Какие бы методы мне ни приходилось вызывать, они всегда общедоступны.   -  person AbrahamJP    schedule 11.01.2011


Ответы (6)


Читаемый\Поддерживаемый код

Конечно верно по моему опыту.

Меньше строк кода.

Не существенно, но поможет.

Влияет на производительность приложений.

Очень немного. Но даже близко не так, как отражение.

Динамическое ключевое слово является внутренней оболочкой Reflection.

Совершенно не соответствует действительности. Ключевое слово dynamic использует среду выполнения динамической библиотеки.

[Изменить: исправление согласно комментарию ниже]

Казалось бы, Dynamic Language Runtime действительно использует Reflection, и повышение производительности происходит только за счет методов кэширования.

Динамическая типизация может превратиться в рассадник трудно обнаруживаемых ошибок.

Это может быть правдой; это зависит от того, как вы пишете свой код. Вы эффективно удаляете проверку компилятором из своего кода. Если у вас хорошее тестовое покрытие, это, вероятно, не будет иметь значения; если нет, то я подозреваю, что вы столкнетесь с проблемами.

Влияет на совместимость с предыдущими версиями .NET.

Не правда. Я имею в виду, что вы не сможете скомпилировать свой код для более старых версий, но если вы хотите это сделать, вам следует использовать старые версии в качестве основы и скомпилировать их, а не наоборот. Но если вы хотите использовать библиотеку .NET 2, у вас не должно возникнуть слишком много проблем, если вы включите объявление в app.config/web.config.

Одно существенное преимущество, которое вы упускаете, — это улучшенная совместимость с компонентами COM/ATL.

person pdr    schedule 10.01.2011
comment
Поэтому я могу поверить вам на слово, что не будет каких-либо заметных различий в производительности при использовании динамического (DLR) отражения. Спасибо за указание на улучшенную совместимость COM\ATL. - person AbrahamJP; 10.01.2011
comment
@AbrahamJP - использование dynamic быстрее, чем использование отражения, особенно если метод вызывается повторно (из-за кэширования). - person pdr; 10.01.2011
comment
Re Совершенно не соответствует действительности. Ключевое слово dynamic использует динамическую библиотеку времени выполнения. Как именно, по-вашему, это делает DLR? Какая магия есть в его распоряжении, благодаря чему он может выполнять анализ типов во время выполнения без отражения? В DLR нет никакой магии; он использует Reflection, когда ему нужен любой другой код. Он просто очень умен в кэшировании результата, но поверьте мне, он использует отражение. - person Eric Lippert; 10.01.2011
comment
@ Эрик Липперт - я исправлен. Я понял, что это было немного сложнее, чем это - person pdr; 10.01.2011
comment
Это намного сложнее! Не все поставщики анализа DLR используют отражение, но поставщик C#, безусловно, широко использует отражение для выполнения анализа типов во время выполнения. И хотя результат кэшируется, типы среды выполнения, являющиеся ключами кэша, всегда определяются посредством отражения. - person Eric Lippert; 10.01.2011

Пожалуйста, помогите мне понять, разумны ли плюсы и минусы, с которыми я столкнулся, или нет?

Меня беспокоят ваши плюсы и минусы в том, что некоторые из них не учитывают различий между использованием отражения и использованием динамики. Эта динамическая типизация создает ошибки, которые не обнаруживаются до тех пор, пока время выполнения не станет истинным для любой системы динамической типизации. Код отражения с такой же вероятностью может содержать ошибку, как и код, использующий динамический тип.

Вместо того, чтобы думать об этом с точки зрения плюсов и минусов, подумайте об этом более нейтрально. Вопрос, который я бы задал: «Каковы различия между использованием Reflection и использованием динамического типа?»

Во-первых: с Reflection вы получаете точно то, что просили. Используя dynamic, вы получаете то, что сделал бы компилятор C#, если бы ему была предоставлена ​​информация о типе во время компиляции. Потенциально это две совершенно разные вещи. Если у вас есть MethodInfo для определенного метода, и вы вызываете этот метод с определенным аргументом, то вызывается именно этот метод, точка. Если вы используете «динамический», то вы просите DLR во время выполнения определить мнение компилятора С# о том, какой метод является правильным для вызова. Компилятор C# может выбрать метод, отличный от того, который вам действительно нужен.

Во-вторых: с помощью Reflection вы можете (если вашему коду предоставлен достаточно высокий уровень доверия) выполнять приватное отражение. Вы можете вызывать приватные методы, читать приватные поля и так далее. Является ли это хорошей идеей, я не знаю. Мне это, конечно, кажется опасным и глупым, но я не знаю, что у вас за приложение. С динамическим вы получаете поведение, которое вы получили бы от компилятора C#; частные методы и поля не видны.

Третье: с Reflection код, который вы пишете, выглядит как механизм. Похоже, вы загружаете источник метаданных, извлекаете некоторые типы, извлекаете информацию о некоторых методах и вызываете методы для объектов-получателей через информацию о методе. Каждый шаг на этом пути выглядит как работа механизма. С динамическим каждый шаг выглядит как бизнес-логика. Вы вызываете метод получателя так же, как и в любом другом коде. Что важно? В некотором коде механизм на самом деле является самой важной вещью. В некотором коде важнее всего бизнес-логика, которую реализует механизм. Выберите технику, которая подчеркивает правильный уровень абстракции.

В-четвертых: затраты на производительность разные. С Reflection вы не получаете какого-либо кэшированного поведения, что означает, что операции, как правило, выполняются медленнее, но нет затрат памяти на поддержание кеша, и каждая операция стоит примерно одинаково. С DLR первая операция действительно очень медленная, поскольку она выполняет огромный объем анализа, но анализ кэшируется и используется повторно. Это потребляет память в обмен на увеличение скорости последующих вызовов в некоторых сценариях. Каков правильный баланс скорости и использования памяти для вашего приложения, я не знаю.

person Eric Lippert    schedule 10.01.2011
comment
Спасибо за подробный разбор моего запроса. Было приятно узнать, что DLR кэширует результаты анализа. - person AbrahamJP; 11.01.2011
comment
Это, безусловно, лучший ответ на этот вопрос - person Keith Jackson; 04.11.2014

Между Dynamic и Reflection есть 4 больших различия. Ниже приводится подробное объяснение того же самого. Ссылка на http://www.codeproject.com/Articles/593881/What-is-the-difference-between-Reflection-and-Dyna

Пункт 1. Проверка VS Invoke

Отражение может делать две вещи: во-первых, оно может проверять метаданные, а во-вторых, оно также имеет возможность вызывать методы во время выполнения. В то время как в Динамическом мы можем вызывать только методы. Поэтому, если я создаю программное обеспечение, такое как Visual Studio IDE, тогда отражение - это путь. Если мне просто нужен динамический вызов из моего кода С#, динамический - лучший вариант.

DynamicVsReflection

Пункт 2. Приватный и публичный вызов

Вы не можете вызывать приватные методы с помощью dynamic. В отражении можно вызывать частные методы.

Пункт 3. Кэширование

Dynamic использует внутреннее отражение, а также добавляет преимущества кэширования. Поэтому, если вы хотите просто динамически вызывать объект, лучше всего использовать Dynamic, поскольку вы получаете преимущества в производительности.

Пункт 4. Статические классы

Dynamic зависит от экземпляра: у вас нет доступа к статическим членам; вы должны использовать Reflection в этих сценариях.

person Shivprasad Koirala    schedule 21.05.2013

В большинстве случаев использование динамического ключевого слова не приводит к значительному сокращению кода. В некоторых случаях это будет; это зависит от провайдера, и поэтому это важное различие. Вам, вероятно, никогда не следует использовать ключевое слово dynamic для доступа к простым объектам CLR; польза там слишком мала.

Ключевое слово dynamic подрывает автоматические инструменты рефакторинга и делает модульные тесты с высоким охватом более важными; в конце концов, компилятор почти ничего не проверяет, когда вы его используете. Это не такая большая проблема, когда вы взаимодействуете с очень стабильным или по своей сути динамически типизированным API, но это особенно неприятно, если вы используете ключевое слово dynamic для доступа к библиотеке, чей API может измениться в будущем (например, любой код, который вы сами пишете). ).

Используйте ключевое слово экономно там, где это имеет смысл, и убедитесь, что такой код имеет достаточные модульные тесты. Не используйте его там, где он не нужен или где вывод типа (например, var) может сделать то же самое.

Изменить. Ниже вы упомянули, что делаете это для подключаемых модулей. Managed Extensibility Framework была разработан с учетом этого - это может быть лучший вариант, чем ключевое слово dynamic и отражение.

person Eamon Nerbonne    schedule 10.01.2011
comment
@Eamon: Как уже упоминалось, я не использую динамическое ключевое слово для доступа к простым объектам CLR, вместо этого приложение, о котором я упоминал, предоставляет модель подключаемого модуля для обработки новых функций, поскольку это отражение широко используется. Чтобы сделать этот модуль эффективным и удобным в сопровождении, я не мог решить, использовать ли ключевое слово Reflection или Dynamic. Главная проблема для меня — производительность. - person AbrahamJP; 10.01.2011
comment
@AbrahamJP Поддерживается ли ваша модель плагина через интерфейсы или по соглашению? Если он поддерживается с помощью интерфейсов, то в любом случае необходимо использовать небольшое отражение. - person Tim Lloyd; 10.01.2011
comment
плагины не должны требовать динамической типизации. Есть ли проблема с производительностью, зависит от того, что вы делаете (миллионы мелких вызовов против одного или двух крупных), но априори я не ожидал, что производительность будет проблемой. - person Eamon Nerbonne; 10.01.2011
comment
@Eamon: для модели подключаемых модулей мы используем интерфейсы, а файлы XML используются для обработки некоторых исключительных случаев. Вызов методов, определенных в файле XML, является сложной частью. Мы динамически создаем делегатов для создания функционального контейнера. - person AbrahamJP; 10.01.2011
comment
@Eamon: Спасибо, что указали на Managed Extensibility Framework, я обязательно изучу это. - person AbrahamJP; 10.01.2011

Если вы используете dynamic специально для отражения, вас беспокоит только совместимость с предыдущими версиями. В противном случае он выигрывает у размышлений, потому что он более удобочитаем и короче. В любом случае вы потеряете сильную типизацию и (некоторую) производительность из-за самого использования отражения.

person Stilgar    schedule 10.01.2011

Как я вижу, все ваши минусы для использования динамического, кроме взаимодействия со старыми версиями .NET, также присутствуют при использовании Reflection:

Влияет на производительность приложений

Хотя это влияет на производительность, также влияет и использование Reflection. Из того, что я помню, DLR более или менее использует Reflection при первом доступе к методу/свойству вашего динамического объекта для данного типа и кэширует целевую пару тип/доступ, так что более поздний доступ - это просто поиск в кеше, что делает его быстрее затем отражение

Динамическое ключевое слово является внутренней оболочкой Reflection.

Даже если бы это было правдой (см. выше), разве это было бы отрицательным моментом? Независимо от того, обертывает ли он Reflection, это не должно влиять на ваше приложение в каком-либо существенном вопросе.

Динамическая типизация может превратиться в рассадник трудно обнаруживаемых ошибок

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

Влияет на совместимость с предыдущими версиями .NET.

Для этого вы должны сами решить, насколько это вас беспокоит.

person Grizzly    schedule 10.01.2011