C# 对结构使用ref会导致它存储在堆上吗?
我曾考虑使用一个struct在一个方法中存储几个状态位,但是我希望能够使用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
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