Я создаю карту рассылки сообщений в C # и в основном просто играю с разными подходами.Меня интересует разница в производительности, которую я измеряю, но не понятно почему, глядя на IL.
Карта сообщений:
delegate void MessageHandler(Message message);
AddHandler(Type t, MessageHandler handler)
{
/* add 'handler' to messageMap invocation list */
}
delegate void GenericMessageHandler<T>(T message);
AddHandler<T>(GenericMessageHandler<T> handler) where T: Message
{
AddHandler(typeof(T), e => { handler((T)e); });
}
Dictionary<Type, MessageHandler> messageMap;
У меня тогда есть иерархия классов сообщений,похож на EventArgs в WPF, например:
public class Message {}
public class VelocityUpdateMessage : Message
и классы наблюдателей с функциями обработчиков:
void HandleVelocityUpdate(VelocityUpdateMessage message) { ... }
Я измеряю 2 способа добавления и вызова обработчиков.Я завершаю делегатский вызов, чтобы получить немного концептуальной безопасности типов, и в этом заключается разница в производительности.
Подход 1: вызовы слушателя
AddHandler(typeof(VelocityUpdateMessage),
e => { HandleVelocityUpdate((VelocityUpdateMessage)e); });
Подход 2: вызовы слушателя
AddHandler<VelocityUpdateMessage>(HandleVelocityUpdate);
В обоих подходах создается делегат MessageHandler, который выполняет приведение и вызов одного и того же метода, но вызов делегатов, созданных с использованием подхода # 2, немного медленнее, хотя сгенерированный IL выглядит идентично.Это дополнительные затраты времени выполнения при приведении к универсальному типу?Это ограничение типа?Я ожидаю, что JITted-делегаты будут такими же, как только будет разрешен общий тип.
Спасибо за любую информацию.