虽然我没在大学里学过计算机科学,但我的理解是实现在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的作用域内)存储在哪里?这是如何工作的?它被装箱了吗?如果没有,即使是值类型,它是否现在就会受到垃圾回收的影响?或者内存可以立即被回收?
对于这个冗长的问题我感到抱歉。但即使答案非常简单,也可能对那些将来也会想到同样问题的人有所启发。