在 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()
{
}
}
}
另外,有人可以告诉我这里组件的意义到底是什么吗?我也很难理解这个概念。
I think I understand the use of IntPtr, though I'm really not sure.
I copied the IDisposable pattern from MSDN just to see what I could get from it, and while I understand it for the most part, I have no idea how to implement an IntPtr properly, or even understand what it is that it's supposed to "point" to, or reference. On top of that, I have no idea how to even assign or cast an integer, string, char, double, etc. to an IntPtr to create a pointer out of it.
Also, does IntPtr require unsafe code use?
Anyway, here's some code just to paint a picture of what I'm talking about:
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()
{
}
}
}
Also, could someone tell me what the point of the component here is, exactly? I'm also having trouble wrapping my head around this concept as well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以通过以下方式使用 IntPtr 对象:
您可以探索其他
Marshal
方法来了解如何将字符串、双精度等写入 IntPtr。关于您的示例代码的说明 - 处置外部分配的非托管对象不是一个好主意。您应该只处理在类构造函数中分配的对象。这不是严格的规则,而是某种良好的做法。
You can use IntPtr objects this way:
You can explore other
Marshal
method to understand how to write string, doubles and etc to IntPtr.So words about your sample code - its not a good idea to dispose external allocated unmanaged object. You should dispose only object which you have allocated in class constructor. This is not strict rule but some kind of good practice.
IntPtr
< /a> (这个链接实际上说明了我所做的大部分内容)是一种特殊形式的整数,它是进程当前位的指针的大小 - 大小是 4 个字节在 32 位 x86 中,在 64 位 x86 中为 8 个字节,因为这对应于指针的大小。虽然它可以引用内存中的某个位置,但它并不需要这样做。正如在发布的代码中一样,它可以仅引用句柄或其他不透明的数字。它很重要,因为 P/Invoked 系统调用的大小发生了变化(系统调用使用常量大小的整数,而某些系统调用取决于体系结构,而指针始终取决于体系结构)。
IntPtr
本身不需要被释放,但是其中包含的不透明数字可能指的是确实需要释放的资源;这是获取价值的 API 合同的全部部分。请参阅
new IntPtr(long)
和IntPtr.ToInt32/ToInt64
以了解与标准数字类型之间的转换(在 64 位环境中,ToInt32 可能是这样的)
将抛出溢出异常)。不,虽然获取 IntPtr 的值(例如调用 P/Invoked 函数)可能需要适当的安全权限,但没有
unsafe
需要代码(请参阅链接或unsafe
允许的内容)——但可以说任何与本机代码对话的东西都是“不安全的”,因为它可能会导致良好的进程崩溃;-)快乐的编码。
IntPtr
(this link actually says much of what I do) is a special form of integer that is the size of the pointer for the current bit-ness of the process -- the size is 4 bytes in 32bit x86, 8 bytes in 64bit x86, as this corresponds with the size a pointer.While it can refer to a location in memory, it doesn't need to. As in the posted code, it could just refer to a handle or other opaque number. It is important because of the size changes in P/Invoked system calls (system calls use constant-sized integer while some depend on the architecture and pointers are always architecture dependent). An
IntPtr
does not need to be disposed of itself, but the opaque number contained in it may refer to a resource that does need releasing; this is all part of the API contract with where the value was obtained.See
new IntPtr(long)
andIntPtr.ToInt32/ToInt64
for conversions to/from a standard numeric type (on a 64-bit environment it is possible thatToInt32
will throw an overflow exception).And no, while obtaining a value for the
IntPtr
(e.g. calling P/Invoked function) may require the appropriate security permissions, there is nounsafe
code required (see the link or whatunsafe
allows) -- but arguably anything that talks to native code is "unsafe" as it can cause a nice process crash ;-)Happy coding.
IntPtr
只是一种值类型,其大小与目标平台上的指针大小相匹配。主要在处理非托管指针时需要使用它。IntPtr
本身无法被释放,因为它只代表内存中的一个位置。您的清理需要特定于IntPtr
引用的对象。假设您有一个非托管函数,需要窗口句柄来完成其工作。在这种情况下,您可以使用属性Control.Handle
来获取指向控件的窗口句柄的指针。要正确清理控件及其底层窗口,您不必处理引用非托管句柄的IntPtr
,而是处置该控件。An
IntPtr
is only a value type which size matches the size of a pointer on the target platform. You need to use it mainly when dealing with unmanaged pointers. AnIntPtr
itself cannot be disposed, because it only represents a location in memory. Your cleanup needs to be specific to the object referred to by theIntPtr
. Say you have an unmanaged function that needs a window handle to do its work. In this case you can use the propertyControl.Handle
to get a pointer to the window handle of the control. To properly cleanup the control and its underlying window you do not have to take care of theIntPtr
refering to the unmanaged handle, but instead dispose the control.IntPtr 是一个指针大小的整数,在 32 位系统上为 32 位,在 64 位系统上为 64 位。它通常用于包装指针或句柄,以将其传递给非托管函数,就像您所做的那样。 “不安全”意味着您在 C# 代码中使用指针,因此 IntPtr 位于不安全块之外或不允许编译不安全代码。
我也无法告诉您该组件的意义是什么,但它真的,真的不应该存在。句柄应该由一个对象拥有,该对象公开该句柄所代表的功能并负责管理该句柄的生命周期。任意关闭未分配的句柄的类是非常糟糕的设计。
IntPtr is an integer the size of a pointer, 32 bits on 32 bit systems and 64 bits on 64 bit systems. It is typically used to wrap a pointer or handle to be handed off to an unmanaged function as you have done. "unsafe" means you are using pointers in your C# code, so IntPtrs outside of unsafe blocks or with out allowing unsafe code to be compiled.
I also can't tell you what the point of that component but it really, really shouldn't exist. Handles should be owned by an object the exposes the functionality that the handle represents and be responsible for managing that handle's life cycle. A class that just arbitrarily closes handles that it didn't allocate is frighteningly bad design.