643
Производительность.отражения
При использовании отражения безопасность типов на
этапе компиляции не
контролируется. Так как в отражении активно применяются строки, вы теряете
безопасность типов на этапе компиляции. Допустим, для поиска типа с именем
int
средствами отражения
используется вызов
Type.GetType("int")
; код успеш-
но компилируется, но во время выполнения возвращает
null
, так как с точки
зрения
CLR тип
int
называется
System.Int32
.
Отражение работает медленно. При использовании отражения имена типов
и их члены на момент компиляции не известны — они определяются в процес-
се выполнения, причем все типы и члены идентифицируются по строковому
имени. Это значит, что при отражении постоянно выполняется поиск строк
в метаданных
сборки пространства имен
System.Reflection
. Часто строковый
поиск выполняется без учета регистра, что дополнительно замедляет процесс.
В общем случае вызов метода или обращение к полю или свойству посредством
отражения также работает медленно. При использовании отражения перед вызовом
метода аргументы требуется сначала упаковать в массив и инициализировать его
элементы, а потом при вызове метода извлекать аргументы из
массива и помещать
их в стек потока. Кроме того, CLR приходится проверять правильность числа и типа
параметров, переданных методу. И наконец, CLR проверяет наличие у вызывающего
кода разрешений доступа.
В силу этих причин лучше не использовать отражение
для обращения к полям
или вызова методов/свойств. Если вы пишете приложение, которое динамически
ищет и создает объекты, следуйте одному из перечисленных далее подходов.
Порождайте свои типы от базового типа, известного на момент компиляции.
Затем, создав экземпляр своего типа во время выполнения, поместите ссылку
на него в переменную базового типа (выполнив приведение типа) и вызывайте
виртуальные методы базового типа.
Реализуйте в
типах интерфейсы, известные на момент компиляции. Затем,
создав экземпляр своего типа во время выполнения, поместите ссылку на него
в переменную того же типа, что и интерфейс (выполнив приведение типа), и вы-
зывайте методы, определенные в интерфейсе.
Я предпочитаю второй подход, так как в первом случае разработчику невозмож-
но выбрать базовый тип, оптимальный для конкретной ситуации.
Хотя методика
порождения своего типа от базового лучше в отношении контроля версий, потому
что вы всегда добавляете члены в базовый тип и наследуете от него свой тип, но не
можете добавить члены в интерфейс без принудительного изменения программного
кода
всех типов, реализующих этот интерфейс, и их повторной компиляции.
В любом случае я настоятельно рекомендую определять базовый тип или интер-
фейс в их собственной сборке — будет меньше проблем с управлением версиями.
Подробнее об этом см. раздел «Создание приложений с поддержкой подключаемых
компонентов».