在C#中使用正确的IntPtr

我理解IntPtr的使用,虽然我真的不确定。

我从MSDN复制IDisposable模式只是为了看看我能从中得到什么,虽然我大部分时间都理解它,但我不知道如何正确实现IntPtr,或者甚至不知道它应该“指向什么” “参考或参考。 最重要的是,我不知道如何为IntPtr分配或转换整数,字符串,字符,双精度等来创建指针。

此外,IntPtr是否需要使用不安全的代码?

无论如何,这里有一些代码只是为了描绘我正在谈论的内容:

namespace Utilities { class Disposer : IDisposable { private IntPtr handle; private Component component = new Component(); private bool disposed = false; public Disposer(IntPtr handle) { this.handle = handle; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if(!this.disposed) { if (disposing) { component.Dispose(); } CloseHandle(handle); handle = IntPtr.Zero; disposed = true; } } [System.Runtime.InteropServices.DllImport("Kernal32")] private extern static Boolean CloseHandle(IntPtr handle); } public unsafe class ExecuteMain { Object nuller = new Object(); byte boa = 0; byte *blargh = boa; public static void Main() { } } } 

此外,有人可以告诉我这里的组件有什么意义吗? 我也很难绕过这个概念。

您可以这样使用IntPtr对象:

  int test = 55; // Allocating memory for int IntPtr intPointer = Marshal.AllocHGlobal(sizeof(int)); Marshal.WriteInt32(intPointer,test); // sending intPointer to unmanaged code here //Test reading of IntPtr object int test2 = Marshal.ReadInt32(intPointer); // test2 would be equal 55 // Free memory Marshal.FreeHGlobal(intPointer); 

您可以探索其他Marshal方法,以了解如何将字符串,双精度等写入IntPtr。

所以关于你的示例代码的话 – 处理外部分配的非托管对象不是一个好主意。 您应该只处置在类构造函数中分配的对象。 这不是严格的规则,而是某种良好的做法。

IntPtr (这个链接实际上说的是我做的很多)是一个特殊forms的整数,它是进程当前位的指针大小 – 大小是32位x86中的4个字节,64位x86中的8个字节,因为这与指针的大小相对应。

虽然它可以引用内存中的位置,但它不需要。 与发布的代码一样,它可以仅引用句柄或其他不透明数字。 这很重要,因为P / Invoked系统调用的大小更改(系统调用使用常量大小,而有些依赖于体系结构,指针总是依赖于体系结构)。 IntPtr不需要自行处理,但其中包含的不透明数字可能指的是需要释放的资源; 这是获得价值的API合同的所有部分。

请参阅new IntPtr(long)IntPtr.ToInt32/ToInt64以获取与标准数字类型IntPtr.ToInt32/ToInt64的转换(在64位环境中, ToInt32可能会抛出溢出exception)。

不,虽然获取IntPtr的值(例如调用P / Invoked函数)可能需要适当的安全权限,但不需要unsafe代码(请参阅链接或unsafe ) – 但可以说是与本机代码对话的任何内容是“不安全”,因为它可以导致一个很好的过程崩溃;-)

快乐的编码。

IntPtr只是一种值类型,其大小与目标平台上指针的大小相匹配。 您需要主要在处理非托管指针时使用它。 IntPtr本身无法处理,因为它只代表内存中的位置。 您的清理需要特定于IntPtr引用的对象。 假设您有一个需要窗口句柄来完成其工作的非托管函数。 在这种情况下,您可以使用属性Control.Handle获取指向控件的窗口句柄的指针。 要正确清理控件及其底层窗口,您不必处理引用非托管句柄的IntPtr ,而是处理控件。

 [DllImport("UnmanagedLibrary.dll")] private static void DoSomethingWithWindowHandle(IntPtr windowHandle); private void Foo() { Form form = new Form(); // ... DoSomethingWithWindowHandle(form.Handle); // ... form.Dispose(); } 

IntPtr是指针大小的整数,32位系统上的32位和64位系统上的64位。 它通常用于包装指针或句柄,以便像您一样将其移交给非托管函数。 “unsafe”意味着你在C#代码中使用指针,因此IntPtrs不安全的块之外或者不允许编译不安全的代码。

我也无法告诉你该组件的重点是什么,但它确实应该不存在。 句柄应由对象拥有,公开句柄所代表的function,并负责管理句柄的生命周期。 只是任意关闭它没有分配的句柄的类是可怕的糟糕设计。