做int参数获取框?

Paw*_*hra 19 .net c# recursion

说我有以下代码:

void Main()
{
    int a = 5;
    f1(ref a);
}

public void f1(ref int a)
{
    if(a > 7) return;
    a++;
    f1(ref a);
    Console.WriteLine(a);
}
Run Code Online (Sandbox Code Playgroud)

输出是:

8 8 8 
Run Code Online (Sandbox Code Playgroud)

即,当堆栈展开时,保持ref参数的值.

这是否意味着将ref keywordint parameter使其得到盒装?
在递归调用期间,实际堆栈如何?

All*_*hty 25

通过引用传递值类型会导致其在堆栈上的位置传递而不是值本身.它与装箱拆箱无关.这使得在递归调用期间堆栈的外观变得相当容易,因为每个调用都指向堆栈上的"相同"位置.

我认为很多混淆来自MSDN关于拳击和拆箱的段落:

Boxing是给定进程的名称,其中值类型被转换为引用类型.当您装入变量时,您将创建一个指向堆上的新副本的引用变量.引用变量是一个对象,...

您可能会在两个不同的事物之间混淆:1)按照您的意愿"转换"一个值类型来表示一个对象,根据定义它是一个引用类型:

int a = 5;
object b = a; // boxed into a reference type
Run Code Online (Sandbox Code Playgroud)

2)与值类型参数的通过由参考:

main(){
   int a = 5;
   doWork(ref a);
}
void doWork(ref int a)
{
    a++;
}
Run Code Online (Sandbox Code Playgroud)

这是两件不同的事情.

  • 可能是最好的解释......注意"在堆栈上"是问题中提到的特定情况,值类型不必在堆栈上分配.也许说"绝对位置(即在堆栈上)"可能更通用 - 不确定它如何为没有C/C++背景的人阅读. (3认同)

小智 9

创建一个程序可以很容易地给出不同的结果,具体取决于是否ref int装箱:

static void Main()
{
    int a = 5;
    f(ref a, ref a);
}

static void f(ref int a, ref int b)
{
    a = 3;
    Console.WriteLine(b);
}
Run Code Online (Sandbox Code Playgroud)

你得到了什么?我看到3印刷了.

拳击涉及创建副本,所以如果ref a盒装,输出将是5.相反,无论是ab是原来的引用a变量Main.如果它有帮助,你可以大多数(不完全)将它们视为指针.


usr*_*usr 5

在现有答案中添加这是如何实现的:

CLR 支持所谓的托管指针。 ref将托管指针传递到堆栈上的变量。您还可以传递堆位置:

var array = new int[1];
F(ref array[0]);
Run Code Online (Sandbox Code Playgroud)

您还可以传递对字段的引用。

这不会导致固定。运行时(特别是 GC)可以理解托管指针。它们是可重定位的。它们是安全且可验证的。