почему вызов метода путем отражения через интерфейс намного быстрее

#c# #reflection #interface

#c# #отражение #интерфейс

Вопрос:

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

  // first version
  class A
    {
        public void fn()
        { 
        }
    }
  void Main(String[]x)
  {
        Type type = typeof(A);
        object obj = Activator.CreateInstance(type);
        type.InvokeMember("fn", BindingFlags.Public, null, obj, null);
  }

  //second verison
   interface IA
    {
        void fn();
    }

    class A :IA
    {
        public void fn()
        {
        }
    }

 void Main(String []x)
 {
        Type type = typeof(A);
        IA obj =(IA) Activator.CreateInstance(type);
        obj.fn();
 }
 

Комментарии:

1. Во втором примере вы не отражаете вызов метода; все, что вы делаете, это обычный вызов метода. Кроме того, вы не предоставили никаких тестов.

Ответ №1:

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

Методы интерфейса, напротив, вызываются с помощью обычной callvirt инструкции с использованием vtable.

Комментарии:

1. как насчет метода invoke menber, какой метод он использовал?

2. InvokeMember , как и остальная часть Type класса, является отражением.

Ответ №2:

Для сравнения яблок с яблоками вызовите Type.getConstructor, чтобы получить объект ConstructorInfo и вызвать его для создания вашего объекта. Затем вы можете сохранить ConstructorInfo и повторно использовать. Активатор очень медленный в сравнении.

Отвечая на ваш вопрос о том, как работает способ отражения:

Activator выполняет поиск в метаданных загруженных сборок имени типа, соответствующего указанному вами. Затем он ищет конструктор, похожий на Type.getConstructor , который возвращает ConstructorInfo . Он вызывает этот конструктор и возвращает объект.

Затем, когда вы вызываете Type .InvokeMember, вы снова используете отражение, запрашивая метаданные класса, чтобы найти соответствующую сигнатуру метода. Это возвращается как MethodInfo, который затем вызывается.

Тяжелая работа в отражении — это не сам вызов, а поиск метаданных для типа, конструктора и метода. Вот почему я говорил, что вы можете выполнять относительно высокопроизводительные вызовы методов для отраженных объектов, повторно используя объекты ConstructorInfo и MethodInfo . Вы найдете многократный вызов MethodInfo .Вызов намного быстрее, чем ввод.InvokeMember

Комментарии:

1. Я не согласен. Если вы разбиваете вызов Activator и вызов invoke member на их фактические реализации, это включает получение ContructorInfo и MethodInfo . Интерфейсы используют или статический вызов метода, который не требует поиска MethodInfo