Пожалуйста, помогите мне понять, разумны ли плюсы и минусы, с которыми я столкнулся, или нет?
Меня беспокоят ваши плюсы и минусы в том, что некоторые из них не учитывают различий между использованием отражения и использованием динамики. Эта динамическая типизация создает ошибки, которые не обнаруживаются до тех пор, пока время выполнения не станет истинным для любой системы динамической типизации. Код отражения с такой же вероятностью может содержать ошибку, как и код, использующий динамический тип.
Вместо того, чтобы думать об этом с точки зрения плюсов и минусов, подумайте об этом более нейтрально. Вопрос, который я бы задал: «Каковы различия между использованием Reflection и использованием динамического типа?»
Во-первых: с Reflection вы получаете точно то, что просили. Используя dynamic, вы получаете то, что сделал бы компилятор C#, если бы ему была предоставлена информация о типе во время компиляции. Потенциально это две совершенно разные вещи. Если у вас есть MethodInfo для определенного метода, и вы вызываете этот метод с определенным аргументом, то вызывается именно этот метод, точка. Если вы используете «динамический», то вы просите DLR во время выполнения определить мнение компилятора С# о том, какой метод является правильным для вызова. Компилятор C# может выбрать метод, отличный от того, который вам действительно нужен.
Во-вторых: с помощью Reflection вы можете (если вашему коду предоставлен достаточно высокий уровень доверия) выполнять приватное отражение. Вы можете вызывать приватные методы, читать приватные поля и так далее. Является ли это хорошей идеей, я не знаю. Мне это, конечно, кажется опасным и глупым, но я не знаю, что у вас за приложение. С динамическим вы получаете поведение, которое вы получили бы от компилятора C#; частные методы и поля не видны.
Третье: с Reflection код, который вы пишете, выглядит как механизм. Похоже, вы загружаете источник метаданных, извлекаете некоторые типы, извлекаете информацию о некоторых методах и вызываете методы для объектов-получателей через информацию о методе. Каждый шаг на этом пути выглядит как работа механизма. С динамическим каждый шаг выглядит как бизнес-логика. Вы вызываете метод получателя так же, как и в любом другом коде. Что важно? В некотором коде механизм на самом деле является самой важной вещью. В некотором коде важнее всего бизнес-логика, которую реализует механизм. Выберите технику, которая подчеркивает правильный уровень абстракции.
В-четвертых: затраты на производительность разные. С Reflection вы не получаете какого-либо кэшированного поведения, что означает, что операции, как правило, выполняются медленнее, но нет затрат памяти на поддержание кеша, и каждая операция стоит примерно одинаково. С DLR первая операция действительно очень медленная, поскольку она выполняет огромный объем анализа, но анализ кэшируется и используется повторно. Это потребляет память в обмен на увеличение скорости последующих вызовов в некоторых сценариях. Каков правильный баланс скорости и использования памяти для вашего приложения, я не знаю.
person
Eric Lippert
schedule
10.01.2011