分配给引用类型变量的指针/引用的隐藏值是多少?

时间:2018-01-04 11:36:46

标签: c# value-type reference-type

int number = 1

number的值为1,因为它是值类型

分配给引用类型变量的指针的实际值是什么?

是int还是字符串?还是有点位?如果你把它写出来会是什么样子?是否可以使用该值为变量分配引用?

Question harrysQuestion = new Question();

harrysQuestion只是新问题的指针或引用。那指针的价值是什么?如果我执行此操作,则分配给另一个Question变量的值相同:

Question harrysQuestionAgain = harrysQuestion;

这是一个指向我计算机内存中某个位置的数字吗?它是幕后的实际C#值变量吗?

1 个答案:

答案 0 :(得分:3)

  

这是一个指向我计算机内存中某个位置的数字吗?

从概念上讲,引用和指针是分开但相关的。实际上它们虚拟可以互换,区别在于GC知道如何行走和修复引用(垃圾收集等),而不是指针(还有其他关于fixed如何工作的事情就值的破解而言,允许在堆栈上找到的引用被解释为"固定"便宜)。实际上,在所有实现中(出于性能原因),它们如此接近,您可以将它们视为 kinda 相同。

您实际上想要获取"值"这是非常罕见的。引用(而不是取消引用它),除非你首先固定对象,否则你需要非常小心这样做,因为地址可以改变(并且指针版本将不会被纠正)。对于这个用例的需求实际上稍微增加与即将到来的"管道"工作,所以Unsafe实用程序类型的corefxlab / myget版本实际上提供了一些方法来促进引用/指针的交换(包括内部指针/引用到对象中),但是:除非你做了一些低的事情等级,你可能永远不需要那个。

每个请求(评论):我提到了#34;固定&#34;和#34;固定&#34; - 这里的问题是.NET有一个&#34;压缩&#34;垃圾收集器,允许在运行时移动对象,只要它承诺修复所有引用,确保您从未在托管代码中注意到这一点。 没有承诺的是修复指针。所以:如果您要将任何对象看作指针,您需要告诉运行时(特别是:垃圾收集器)不要移动该对象< / strong>,或者至少直到你告诉它你已经完成了。这就是&#34;固定&#34;是。 &#34; pin&#34;有两种方法:

  • 对于长期引脚(通常类似于byte[]缓冲区,您将作为对象中的字段存储并作为指针传递给非托管代码),您可以使用{{ 1}}针对一个对象,它记录在GC知道要查看的全局结构中
  • 对于在堆栈上的引用的短期引脚,GCHandle关键字执行一些伏都教,让GC(总是查看每个堆栈)知道引用 - 因此,对象引用(该地址的对象) - 应该被认为是固定的,没有需要不断添加/删除到全局结构

作为一个有趣的旁注:&#34;内部参考&#34;对值类型的引用是一个仅存在于的概念 - 而不是作为字段的类型可能最终存在于堆上(这意味着任何{{1} }或fixed除了新的class概念)。它们的工作方式与常规引用相同,但这些引用的目标是内容本身,而不是对象头的开头。这意味着

struct

ref struct

var fieldReference = ref this._someField;

在方法中工作,只要该内部引用仅在堆栈上(即没有SomeOtherMethod(ref this._someField); / SomeOtherMethod(ref someArray[index]); / capture-variables / etc); GC很乐意为解决对象的内部指针但仅为解决堆栈的开销 - 减少所涉及的工作的整体规模。