在C#中,方法调用时的上下文信息(如参数,局部变量和返回地址)主要存储在栈中,但具体细节取决于数据类型和上下文。
- 栈:
- 栈帧:每次方法调用时,会在栈上分配一个栈帧,用于存储:
- 值类型的局部变量(int,struct等)。
- 方法参数(值类型直接存储,引用类型存储堆中数据的引用)。
- 返回地址(方法执行完后要跳转的地方)。
- 生命周期:栈帧在结束时自动释放。
- 栈帧:每次方法调用时,会在栈上分配一个栈帧,用于存储:
- 堆:
- 引用类型的实例:如果方法内部创建了类对象,对象本身存储在堆中,栈中保存数据在堆中的引用。
- 闭包或异步上下文:若局部变量被lambda表达式或异步方法捕获(如async),编译器会生成闭包类,将这些变量移至堆中,以延长其生命周期。
实例:
void MyMethod() {
int a = 10; // 值类型,存储在栈中。
string b = "Hello"; // 引用类型,b的指针在栈中,"Hello"字符串在堆中。
var c = new MyClass(); // c的指针在栈中,对象实例在堆中。
}
特殊情况:
- 装箱操作:当值类型被转换为0bject时,会装箱到堆中。
- 迭代器方法(yield return)或异步方法(async/await):状态机可能将局部变量移至堆,以保持跨异步操作的状态。 总结:方法调用的核心上下文(值类型变量/参数,返回地址)在栈中,涉及引用类型或特殊上下文时堆会参与存储。