C# 在C语言中正确使用IntPtr#

C# 在C语言中正确使用IntPtr#,c#,idisposable,intptr,C#,Idisposable,Intptr,我想我理解IntPtr的用法,尽管我真的不确定 我从MSDN复制了IDisposable模式,只是想看看我能从中得到什么,虽然我大部分都理解它,但我不知道如何正确地实现IntPtr,甚至不知道它应该“指向”或引用什么。除此之外,我甚至不知道如何将整数、字符串、char、double等赋值或强制转换到IntPtr以创建指针 此外,IntPtr是否需要不安全的代码使用 不管怎样,这里有一些代码只是为了描绘我所说的内容: namespace Utilities { class Dispo

我想我理解IntPtr的用法,尽管我真的不确定

我从MSDN复制了IDisposable模式,只是想看看我能从中得到什么,虽然我大部分都理解它,但我不知道如何正确地实现IntPtr,甚至不知道它应该“指向”或引用什么。除此之外,我甚至不知道如何将整数、字符串、char、double等赋值或强制转换到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是指针大小的整数,32位系统为32位,64位系统为64位。它通常用于包装要传递给非托管函数的指针或句柄,就像您所做的那样。“不安全”意味着您在C#代码中使用指针,因此INTPTR位于不安全块之外或不允许编译不安全代码


我也不能告诉你这个组件的意义,但它真的,真的不应该存在。句柄应由对象拥有,该对象公开句柄表示的功能,并负责管理该句柄的生命周期。一个仅仅任意关闭它没有分配的句柄的类是非常糟糕的设计。

一个
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();
}
(这个链接实际上说明了我所做的大部分工作)是一种特殊形式的整数,它是进程当前位的指针大小——32位x86中的大小为4字节,64位x86中的大小为8字节,因为这与指针的大小相对应

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

请参见
new IntPtr(long)
IntPtr.ToInt32/ToInt64
,了解与标准数字类型之间的转换(在64位环境中,
ToInt32
可能会引发溢出异常)

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


快乐编码。

您可以通过以下方式使用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);
您可以探索其他方法来了解如何将字符串、双精度等写入IntPtr


因此,关于您的示例代码的话—处置外部分配的非托管对象不是一个好主意。您应该只处理在类构造函数中分配的对象。这不是严格的规定,而是某种良好的实践

如果您只是尝试跟踪Windows内核对象的句柄,请使用
SafeHandle
:10年后,有没有更简单的方法?