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

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

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

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

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

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

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

6 ответов

Решение

Читаемый \ Обслуживаемый код

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

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

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

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

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

Ключевое слово Dynamic - это внутренняя оболочка Reflection.

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

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

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

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

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

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

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

Одним из важных недостатков, который вам не хватает, является улучшенная совместимость с компонентами COM/ATL.

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

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

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

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

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

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

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

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

Пункт 1. Осмотреть VS Invoke

Reflection может делать две вещи: во-первых, он может проверять метаданные, а во-вторых, он также может вызывать методы во время выполнения. В Dynamic мы можем вызывать только методы. Так что, если я создаю программное обеспечение, как Visual Studio IDE, то рефлексия - путь. Если я просто хочу динамический вызов из моего кода C#, динамический является лучшим вариантом.

DynamicVsReflection

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам