int number = 1
number的值为1,因为它是值类型
分配给引用类型变量的指针的实际值是多少?
它是int还是字符串?还是有点位?如果你把它写出来会是什么样子?是否可以使用该值为变量分配引用?
Question harrysQuestion = new Question();
harrysQuestion只是新问题的指针或引用。那指针的价值是什么?如果我执行此操作,则分配给另一个Question变量的值相同:
Question harrysQuestionAgain = harrysQuestion;
这个数字是否指向我计算机内存中的某个位置?它是幕后的实际C#值变量吗?
这个数字是否指向我计算机内存中的某个位置?
从概念上讲,引用和指针是分开但相关的。实际上它们实际上是可以互换的,区别在于GC知道如何行走和修复引用(垃圾收集等),而不是指针(还有其他一些关于fixed
如何在值的黑客方面起作用的事情,允许在堆栈上找到的参考值被解释为便宜地“固定”)。实际上,它们在所有实现中都非常接近(出于性能原因),您可以将它们视为有点相同。
您实际上想要获得引用的“值”(而不是取消引用它)是非常罕见的,除非您首先固定对象,否则您需要非常小心这样做,因为地址可以更改(并且指针版本不会被更正)。对于这个用例的需求实际上随着即将到来的“管道”工作而略有增加,因此Unsafe
实用程序类型的corefxlab / myget版本实际上提供了一些方法来促进引用/指针的交换(包括内部指针/引用到对象中) ,但是:除非你做的事情很低,否则你可能永远不需要那样做。
每个请求(评论):我提到“固定”和“修复” - 这里的问题是.NET有一个“压缩”垃圾收集器,允许在运行时移动对象,只要它承诺修复所有引用并确保您从未在托管代码中注意到这一点。它没有承诺的是修复指针。所以:如果你要将任何对象看作指针,你需要告诉运行时(特别是:垃圾收集器)根本不要移动那个对象,或者至少在你告诉它你之前重做。这就是“钉扎”的含义。 “pin”有两种方法:
byte[]
缓冲区,你将作为一个字段存储在一个对象中并传递给非托管代码作为指针),你可以对一个对象进行GCHandle
,它会被记录在全局GC知道要看的结构fixed
关键字执行一些voodoo,让GC(总是查看每个堆栈)知道引用 - 因此引用的对象(该地址处的对象) - 应该被认为是固定的,而不需要不断地添加/删除到全局结构作为一个可能有趣的旁注:“内部引用”和对值类型的引用是一个仅存在于堆栈中的概念 - 而不是作为最终可能在堆上的类型的字段(这意味着任何class
或struct
除了新的ref struct
概念)。它们的工作方式与常规引用相同,但这些引用的目标是内容本身,而不是对象头的开头。这意味着
var fieldReference = ref this._someField;
要么
SomeOtherMethod(ref this._someField);
要么
SomeOtherMethod(ref someArray[index]);
只要内部引用只在堆栈上(即没有async
/ yield
/ capture-variables / etc),就可以在方法内部工作; GC很乐意完成解析对象内部指针的开销,但仅限于堆栈 - 以减少所涉及的工作的整体规模。