繁体   English   中英

为什么转换为泛型类型比C#中的显式转换慢?

[英]Why is casting to a generic type slower than an explicit cast in C#?

我正在用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;

然后我有一个Messages类的层次结构,类似于WPF中的EventArgs,例如:

public class Message {}
public class VelocityUpdateMessage : Message

和具有处理函数的observer类:

void HandleVelocityUpdate(VelocityUpdateMessage message) { ... }

我正在测量2种添加和调用处理程序的方法。 我正在包装委托调用,所以我可以获得一些概念类型的安全性,其中存在性能差异。

方法1:听众呼叫

AddHandler(typeof(VelocityUpdateMessage), 
           e => { HandleVelocityUpdate((VelocityUpdateMessage)e); });

方法2:听众呼叫

AddHandler<VelocityUpdateMessage>(HandleVelocityUpdate);

这两种方法都构建了一个MessageHandler委托,它可以进行强制转换和相同的方法调用,但是调用使用方法#2构建的委托,即使生成的IL看起来相同,也会慢一点。 是否会在转换为泛型类型时产生额外的运行时开销? 是类型约束吗? 一旦解决了泛型类型,我希望JITted代理是相同的。

谢谢你的任何信息。

下面的行在每次调用时都会创建一个匿名类型的新实例。 这可能是你表现差异的原因吗?

AddHandler(typeof(T), e => { handler((T)e); }); 

好吧,我不得不看看MethodBody.GetILAsByteArray()IL而不是ILSpy结果让代表们到达底部。 使用通用委托来包装我的消息处理程序并转换消息类型会生成:

0000 : ldarg.0
0001 : ldfld
0006 : ldarg.1
0007 : unbox.any
000C : callvirt void MessageTest.Message+tMessageHandler`1[MessageTest.VelocityUpdateMessage].Invoke(‌​MessageTest.VelocityUpdateMessage) 
0011 : ret

带有显式强制转换的包装器委托生成的位置:

0000 : ldarg.0
0001 : ldarg.1
0002 : castclass
0007 : call void Message.Component.HandleVelocityUpdate(MessageTest.VelocityUpdateMessage)
000C : ret

所以,是的,以这种方式使用泛型的开销很小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM