我知道这是一个实现细节。我实际上很好奇微软的 CLR 中的实现细节是什么。
现在,请耐心等待,因为我没有在大学学习 CS,所以我可能错过了一些基本原则。
但我认为,我对今天在 CLR 中实现的“堆栈”和“堆”的理解是可靠的。例如,我不会做出一些不准确的概括性陈述,例如“值类型存储在堆栈上”。但是,在最常见的场景中——值类型的普通本地变量,或者作为参数传递,或者在方法中声明而不包含在闭包中——值类型变量存储在堆栈中(同样,在 Microsoft 的 CLR 中)。
我想我不确定的是ref
值类型参数的来源。
最初我的想法是,如果调用堆栈看起来像这样(左 = 底部):
A() -> B() -> C()
...那么在A范围内声明并作为ref
参数传递给B的局部变量仍然可以存储在堆栈中——不是吗?B只需要该局部变量存储在A的框架内的内存位置(如果这不是正确的术语,请原谅我;无论如何,我认为我的意思很清楚)。
但是,当我想到我可以做到这一点时,我意识到这不可能完全正确:
delegate void RefAction<T>(ref T arg);
void A()
{
int x = 100;
RefAction<int> b = B;
// This is a non-blocking call; A will return immediately
// after this.
b.BeginInvoke(ref x, C, null);
}
void B(ref int arg)
{
// Putting a sleep here to ensure that A has exited by the time
// the next line gets executed.
Thread.Sleep(1000);
// Where is arg stored right now? The "x" variable
// from the "A" method should be out of scope... but its value
// must somehow be known here for this code to make any sense.
arg += 1;
}
void C(IAsyncResult result)
{
var asyncResult = (AsyncResult)result;
var action = (RefAction<int>)asyncResult.AsyncDelegate;
int output = 0;
// This variable originally came from A... but then
// A returned, it got updated by B, and now it's still here.
action.EndInvoke(ref output, result);
// ...and this prints "101" as expected (?).
Console.WriteLine(output);
}
那么在上面的例子中,x
(在A的范围内)存储在哪里?这是如何工作的?是盒装的吗?如果不是,尽管它是一种值类型,但它现在是否需要进行垃圾收集?还是可以立即回收内存?
我为这个冗长的问题道歉。但即使答案很简单,也许这对于那些发现自己在未来想知道同样事情的其他人来说是有用的。