Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 分配给引用类型变量的指针/引用的隐藏值是多少?_C#_Value Type_Reference Type - Fatal编程技术网

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

C# 分配给引用类型变量的指针/引用的隐藏值是多少?,c#,value-type,reference-type,C#,Value Type,Reference Type,number的值为1,因为它是值类型 分配给引用类型变量的指针的实际值是多少 它是整数还是字符串?还是一些碎片?如果你把它写出来会是什么样子?是否可以使用该值为变量分配引用 int number = 1 harrysQuestion只是指向新问题的指针或参考。那么指针的值是多少?如果我这样做,则分配给另一个问题变量的值相同: Question harrysQuestion = new Question(); 它是一个指向我电脑内存中某个位置的数字吗?它是一个实际的C值变量吗 它是一个指向我电

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

分配给引用类型变量的指针的实际值是多少

它是整数还是字符串?还是一些碎片?如果你把它写出来会是什么样子?是否可以使用该值为变量分配引用

int number = 1
harrysQuestion只是指向新问题的指针或参考。那么指针的值是多少?如果我这样做,则分配给另一个问题变量的值相同:

Question harrysQuestion = new Question();
它是一个指向我电脑内存中某个位置的数字吗?它是一个实际的C值变量吗

它是一个指向我电脑内存中某个位置的数字吗

从概念上讲,引用和指针是分开的,但相互关联。实际上,它们实际上是可互换的,区别在于GC知道如何遍历和修复引用(垃圾收集等),但不知道指针(还有其他一些关于
fixed
如何在值中进行破解的事情,允许堆栈上找到的引用值被廉价地解释为“固定”)。事实上,它们在所有实现中都非常接近(出于性能原因),因此您可以认为它们是相同的

很少有人真的想要获取引用的“值”(而不是取消引用),除非先锁定对象,否则需要非常小心,因为地址可能会更改(指针版本不会被更正)。随着即将到来的“管道”工作,对该用例的需求实际上略有增加,因此
Unsafe
实用程序类型的corefxlab/myget版本实际上提供了一些方法来促进引用/指针(包括内部指针/对象引用)的交换,但是:除非你在做一些低级的事情,否则你可能永远都不需要


每个请求(注释):我提到了“固定”和“修复”-这里的问题是.NET有一个“压缩”垃圾收集器,它允许在运行时移动对象,只要它承诺修复所有引用并确保您从未从托管代码中注意到这一点。它不承诺的是修复指针。因此:如果要将任何对象视为指针,则需要告诉运行时(尤其是垃圾收集器)不要移动该对象,或者至少在告诉它您已经完成之前不要移动该对象。这就是“钉住”的含义。“pin”有两种方式:

  • 对于长期pin(通常是
    byte[]
    缓冲区,您要将其存储为对象中的字段并作为指针传递给非托管代码),您可以对对象使用
    GCHandle
    ,该对象记录在GC知道要查看的全局结构中
  • 对于堆栈上的短期引用pin,
    fixed
    关键字做了一些巫术,让GC(总是查看每个堆栈)知道应该将引用以及引用的对象(该地址处的对象)视为pind,而无需不断添加/删除到全局结构

作为一个可能有趣的补充说明:“内部引用”和对值类型的引用是一个仅存在于堆栈上的概念,而不是作为类型上的字段存在于堆上(这意味着除了新的
ref struct
概念之外的任何
class
struct
)。它们的工作原理与常规引用相同,但这些引用的目标是内容本身,而不是对象头的开头。也就是说

Question harrysQuestionAgain = harrysQuestion;


只要内部引用仅在堆栈上,就在方法内部工作(即,无
async
/
yield
/captured variables/etc);GC乐于承担解析对象内部指针的开销,但仅限于堆栈,以减少所涉及工作的总体规模。

这是一个您不必担心的.NET抽象。当.NET执行内存管理时,实际的底层值甚至可能在幕后发生变化。理论上,不同的运行时实现可以用它做完全不同的事情。你是否有一个更具体的问题,关于为什么你可能需要担心它-你是否有需要知道的原因,或者只是好奇(这也很好!)?@James I's just curios/想了解更多关于代码如何工作的知识。+1,尽管可能简要描述一下钉住的作用,在我看来,GC对对象的移动是.NET引用和非托管语言(甚至是这种语言中的引用)指针在该级别(尽管级别一几乎不会处理)之间最大的区别之一。这些“内部引用”,实际上通常是
ref
,由CIL中的“托管指针”实现。我认为说GC不处理指针是误导。GC只处理非托管指针。@hvd确实如此,但在C#术语中,它们是引用(
ref
);我不想说“非托管指针”的主要原因是,这会让人们想到“非托管内存”,当然,我们可以有“非托管指针”(用CIL术语),它们(本质上)是托管对象的内部引用。但你绝对正确。C#dev很少用“指针”来思考,他们实际上是在说“非托管指针”(CIL),所以我。。。故意摆手。
var fieldReference = ref this._someField;
SomeOtherMethod(ref this._someField);
SomeOtherMethod(ref someArray[index]);