他们更受限制。您可以在指针上说 ++,但不能在ref
or上说out
。
编辑评论中有些混乱,所以要绝对清楚:这里的重点是与指针的功能进行比较。您不能执行与/相同ptr++
的操作,即使其寻址内存中的相邻位置。确实(但在这里无关紧要)您可以执行等效的,但那是将其与values的功能进行比较,而不是指针。ref
out
(*ptr)++
可以肯定的是,它们在内部只是指针,因为堆栈不会移动,并且 C# 是经过精心组织的,因此ref
始终out
引用堆栈的活动区域。
编辑再次绝对清楚(如果从下面的示例中还不清楚的话),这里的重点不是/ 只能ref
指向out
堆栈。就是当它指向栈时,语言规则保证不会变成悬空指针。这种保证是必要的(并且在这里相关/有趣),因为堆栈只是根据方法调用退出丢弃信息,没有检查以确保任何引用者仍然存在。
相反,当ref
/out
引用 GC 堆中的对象时,这些对象能够在必要时保持活动就不足为奇了:GC 堆的设计目的是为了在其引用者所需的任何时间长度内保留对象,并且提供固定(参见下面的示例)以支持不能通过 GC 压缩移动对象的情况。
如果您曾经在不安全的代码中使用互操作,您会发现它ref
与指针密切相关。例如,如果一个 COM 接口声明如下:
HRESULT Write(BYTE *pBuffer, UINT size);
互操作程序集会将其变成这样:
void Write(ref byte pBuffer, uint size);
你可以这样做来调用它(我相信 COM 互操作的东西负责固定数组):
byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);
换句话说,ref
第一个字节可以让您访问所有内容;它显然是指向第一个字节的指针。