C# 对结构使用ref会导致它存储在堆上吗?

C# 对结构使用ref会导致它存储在堆上吗?,c#,.net,clr,C#,.net,Clr,我曾考虑使用一个struct在一个方法中存储几个状态位,但是我希望能够使用refkeword将其传递给一个helper方法,以避免按值传递。但是,如果我这样做,那么将存储在堆上,而不是堆栈上 示例代码: var link = new Geoff("Bergen"); Perambulate(ref link); Console.WriteLine(link.Name); void Perambulate(ref Geoff man) { Console.WriteLine("Per

我曾考虑使用一个struct在一个方法中存储几个状态位,但是我希望能够使用
ref
keword将其传递给一个helper方法,以避免按值传递。但是,如果我这样做,那么将存储在堆上,而不是堆栈上

示例代码:

var link = new Geoff("Bergen");

Perambulate(ref link);

Console.WriteLine(link.Name);

void Perambulate(ref Geoff man)
{
    Console.WriteLine("Perambulating {0}",man.Name);
}

struct Geoff
{
    public readonly string Name;

    public Geoff(string name)
    {
        Name = name;
    }
}

我想我真的在问
ref
关键字是否强制将引用值存储在堆上。

不,它不会存储在堆上。它只需将引用传递到其在堆栈上的位置


此外,您的结构设计不好,因为您允许更改名称。结构的内容应该是不可变的。我建议您在本例中使用一个类。

不,它不会。您的结构已在堆栈上。不会因为您已将其引用传递给某个方法而将其移动到堆中。

您的巡视方法只接收对存储在堆栈上的结构的引用(即地址)。

您所指的称为装箱,不,通过引用传递值类型时不会发生装箱。它只会在堆栈上传递对Geoff的引用

将值类型强制转换为引用类型(隐式和显式)时可能会发生装箱。例如:

var g=new Geoff()//值类型
列表对象=新列表()//对象集合(引用类型)
对象。添加(g)//隐式地将g强制转换为对象
这将导致Geoff实例被复制到堆中,这称为装箱


现在,如果您的巡视方法接受一个对象作为参数,那么您传递的Geoff将被装箱并复制到堆中。

根据什么结构的数据应该是不可变的?System.Int32也是一个结构,也不是不可变的,对吗?@MarkusSafar解释了可变结构的问题。Int32是不可变的。例如,你最近一次看到有人重新定义3和100是什么时候?@MarkusSafar有时认为整数是可变的,因为你可以做
integerVariable++
,但是,这编译成
integerVariable=integerVariable+1
,这是一个重新定义,这不是一个修改。@Ceilingfish由于理解结构是值,并且所显示的值是不可变的,这似乎引起了混淆,但是没有要求(甚至C#很遗憾)声明变量必须是不可变的。感谢链接,似乎我(直到现在)从未深入思考和研究过这个主题。但你的观点(至少现在)对我来说绝对合乎逻辑;-)
var g = new Geoff(); //value type
List<object> objects = new List<object>(); //collection of objects (reference type)
objects.Add(g); //implicitly casting g to object