Tar*_*rik 9 .net clr pointers handle
我不能说我有强大的C++背景,所以这些天我经常听到Handle.我知道Pointer是什么(它存储内存位置的地址就像参考),但我不确定Handle是什么以及这两者之间的区别.如果你能提供一个C#中的示例代码就会很棒.
顺便说一下,我用Google搜索了这个术语,然而很多人给出了不同的解释,所以我觉得我从SO中得到了最好的解释.
编辑:
为其他访客快速提醒:句柄就像是指向资源的参考.它可以指向像指针一样的内存地址,但Handle是更通用的术语,所以它更像是一个伪指针.文件就是一个很好的例子.文件可以具有操作系统可以理解并用于查找文件的ID.因此Handle可以保存此ID(可能是也可能不是内存地址),当我们通过此Handle时,OS可以轻松找到该文件.
有关更多详细信息,请参阅以下答案.
编辑:
这个问题下的所有答案都很棒,很有说服力.我很难选择其中一个来标记它作为答案.
句柄只是用作资源替代品的一条信息。
最常见的例子是文件句柄,它通常只是一个整数,分配给您打开的每个文件,以便您可以区分它们。它们在像 C 这样的语言中使用得更频繁,其中所有文件。 open()
返回一个整数,然后在所有其他文件访问函数中,您需要将该值作为参数传递,以便指定您指的是哪个文件。例如,在函数 中int read(int fd, void * ptr, int numbytes)
,您可以将其作为 的参数传入fd
。
C 提供了 3 个听起来很熟悉的标准文件句柄:
在 C# 中,句柄通常被抽象为实现细节,取而代之的是提供一个对象来与之交互。我能想到的最好的例子是(现已弃用)FileStream.Handle属性:
public virtual IntPtr Handle { get; }
Run Code Online (Sandbox Code Playgroud)
手柄是一个标识符,以用于鉴定目的通过一种操作的影响的抽象对象(位图,插座,文件,存储器,等等): ,,HBITMAP
是例如把手的-它们实际上是整数可能代表一个操作系统中某些表或映射中的索引.socket
FILE*
严格来说,指针是内存中的精确位置.虽然指针有时用作句柄,但反转很少(如果有的话)为真.
在面向对象的环境中,句柄被认为是低级实体,将对象包装在对象中是一种很好的做法,对象具有使用分配的句柄调用操作的方法.在这种情况下,你必须持有句柄对象的引用,比如:CBitmap
,System.Net.Sockets.Socket
,std::fstream
等.
如果不钻研语言宗教战争,有些人会争辩说,其中一种更干净,更安全,更快捷,更容易.它几乎总是取决于你所处的环境 - 如果你有选择的话,你不建议直接在C#中使用句柄,而在C中,使用句柄会更简单(和必要).
重要说明:在.Net环境中,如果您必须进行编组,最终将阅读有关被称为句柄的实际对象引用的内容.这是因为它们实际上是在引擎盖下处理而不是指针.因此,当您在对象上调用方法时,编译器实际上是使用句柄来调用该方法,该句柄可以在内存中自由移动.这使得垃圾收集器可以避免内存碎片.因此,System.Drawing.Bitmap
最终得到一个指针到句柄的句柄.
编辑:
例如,C++中的stdio/fstream:
// Read a short line from a file and output it to the console
// 256 bytes max for simplicity purposes
char buffer[256];
// With handle
FILE* file = fopen ("file.txt" , "r");
fgets(buffer, 256 , file);
std::cout << buffer << std::endl;
fclose (file);
// With object reference
{
std::ifstream stream ("file.txt");
stream.getline(buffer, 256);
std::cout << buffer << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
顶部示例使用应被视为FILE*
文件句柄的内容.该file
手柄使用分配fopen
并传递到操作,如fgets()
和close()
.close()
解除分配手柄.
底部示例使用std::ifstream
.句柄在对象构造函数中分配,并且是该对象的内部.要对文件进行操作,请使用该对象提供的方法,例如getline()
.当对象超出范围时,即在结束括号时,流析构函数释放句柄,或者如果在堆上分配了对象,则需要明确地删除它.