【发布时间】:2016-07-10 13:28:32
【问题描述】:
我有WndProc(Message m) 覆盖。这显然被称为很多。假设我希望将一些消息标记为“已处理”。所以我应该将Result 设置为1。但是Result 属性是IntPtr。执行m.Result = new IntPtr(1) 时会发生什么?每次调用都会为一个Int32 值分配内存?如果我创建一个静态的IntPtr 变量并将其设置为new IntPtr(1) 会发生什么?
这样做最正确的方法是什么?
然后我想将m.LParam 与已知值进行比较。也是IntPtr,我可以通过多种方式实现:
if (m.LParam == (IntPtr)0x0001) ...
if ((int)m.LParam == 0x0001) ...
if (m.LParam == myStaticIntPtr1) ...
这种比较的成本是多少?在上述 3 期间,低电平会发生什么? Message 类型不是一次性的。所以我想我可以放心地省略将它传递给base.WndProc(),对吗?当我只想丢弃消息时,什么都不需要做?
额外问题:我不确定,但我想我在 pinvoke.net 上看到了 DllImports,其中 MSDN 文档中的 IntPtrs 已更改为 ints。可能的?它有效吗?发生什么了?隐式转换?
顺便说一句,IntPtr 是托管类型,对吧?因此,如果我不调用非托管代码,也没有使用一次性类型 - 不需要处理任何东西?
【问题讨论】:
-
你在大量想太多了。这些是内置的基本类型;内存分配并不昂贵。此外,在这种情况下,您正在设置结构中字段的值,因此内存已经分配。所有这些操作几乎都是免费的。它们在性能方面都是等效的。从语义上讲,更喜欢将常量转换为 IntPtr,而不是将 IntPtrs 转换为 int。
-
IntPtr 是一个指向非托管对象的 32 位整数。非托管对象位于共享内存(静态)中,不像托管对象那样位于执行堆栈上。如果您使用 IntPtr 或 int 应该没有区别,除非指针没有签名,所以 uint 会更好。 (IntPtr)0x0001 没有任何意义,因为它会指向内存位置 0x0001。
-
另外,您在这里的一个问题中问了太多问题。试图简单地回答其中的一些......不,您应该始终将消息传递给基类的窗口过程。不,将 int 用于指针类型的 DllImport 签名是错误且损坏的;不要那样做。是的,IntPtr 是托管类型,但 CLR 编组器识别它并将这些值正确编组为指针。但它们仍然是指向非托管对象的指针,因此这些非托管对象需要按照文档要求进行处置/删除/释放/关闭。
-
如果您准备好进行微优化(假设您没有陷入过早优化的陷阱),您可以使用MeasureIt
-
谢谢。最好问,而不是猜测;)我不确定我是否做对了。我不确定那里是否需要微优化。可能不是。由于控件是多线程的,因此正确的线程同步对控件响应能力的影响更大。
标签: c# winforms-interop