.net - Boxing vs ValueType 引用;有什么不同?

标签 .net memory boxing

最近有几个关于将 ValueType 装箱为对象的问题,特别是它是否发生在某些情况下。

我意识到我不知道的是,“装箱”一个 ValueType(将其视为引用对象)与简单地通过引用访问它之间有什么区别,例如使用 ref 或 out 关键字(您传递的内容只是“指针”)?在这两种情况下,值都在您可以指向它的某个地方(对于 Object 它是堆,对于本地范围的 ValueType,它是......究竟在哪里?)。

如果我不得不猜测,根据我对 C++ 的了解,我会说它是这样工作的:通过引用访问的 ValueType(假设通过参数关键字)保留在其作用域的调用堆栈级别,但是“指向该变量在堆栈中的存储桶的“快捷方式”指针被创建并成为堆栈下一层的一部分。因为该值已经存储在内存中(甚至可能是 CPU 缓存),所以您不必在堆上实例化新的东西;唯一的新东西是指针,它是它自己的 ValueType(一个 IntPtr)并且它本身存储在堆栈中,因此 AFAIK 比将某些东西放入堆中要快。

这是正在发生的事情,还是有其他事情正在发生?

编辑:更清晰:

public void TakesAnObject(Object obj) {...}

public void TakesAnIntValueType(ref int myValue) {...}

public void AnotherIntParameterMethod(out int myValue) {...}

...

//this locally-scoped variable is simply created on the stack.
int myInt = 5;    

//Performs boxing; an Object is instantiated in the heap that holds the 
//variable value from the stack, and that is passed by ref.
TakesAnObject(myInt);

//Apparently does NOT perform boxing, but we're still dealing with a reference.
//So what's going on?
TakesAnIntValueType(myInt);

//Again created on the stack, with the default 0.
int anotherInt;

//Again, apparently no boxing, but we're dealing with a reference to anotherInt.
AnotherIntParameterMethod(anotherInt);

最佳答案

类引用可以自由复制,并且可以无限期存在。人们可以将它们视为对象的标识符,这些对象(始终)作为独立项目存储在堆上。为了避免过度使用术语“引用”,我喜欢将它们视为 ObjectID。

当例程通过引用接受参数时,该引用是一种特殊类型的东西,它在普通类系统之外(我将其称为 ParameterReference)。与可以无限期存在的 ObjectID 不同,ParameterReference 只允许在被调用函数的持续时间内存在。此外,与始终保存对独立对象的引用的 ObjectID 不同,ParameterReference 保存对堆栈上的局部变量、类 Object 中的字段、数组中的项或自身具有的结构中的字段的引用。匹配这些描述之一。如果 ParameterReference 指向一个局部变量,一旦它超出范围,该变量将不复存在;在此之后尝试使用 ParameterReference 可能会导致数据损坏。然而,由于变量的范围至少会扩展到被调用的例程退出,并且因为那时 ParameterReference 将不复存在,所以 ParameterReference 访问不再存在的变量是没有危险的。

关于.net - Boxing vs ValueType 引用;有什么不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4807659/

相关文章:

.net - 使用线程时的socket问题

C++内存泄漏,如何检测

Java 拒绝启动 - 无法为对象堆保留足够的空间

c# - 运行时默认值不相等

C# WinForm + Barcode Scanner 输入,TextChanged 错误

c# - NServiceBus 批处理长时间运行的作业

ios滚动过一个大的uiview内存问题

Scala 2.10、Double.isNaN 和拳击

c# - Array 中会发生装箱和拆箱吗?

c# - 使表格在函数C#中可用