Ref -参数-栈或堆
本文关键字:参数 Ref | 更新日期: 2023-09-27 17:49:47
这只是一个理论问题,但我无法得到一个好的答案:
如果我通过ref
传递参数,则传递对象本身,而不是副本。
让我困惑的是:据我所知,每个方法都有自己的堆栈帧-内存,它们不能离开。那么这是否意味着一个ref - Object被打包在堆上,并且有一个对这个参数的引用,或者这个方法进入调用方法的堆栈并在那里工作?
如果我的问题令人困惑,我很抱歉,我基本上想知道ref类型是如何保存的,以及它有什么影响。
伊迪丝:我想我没有说清楚。我理解值和引用类型的概念。为了更简单,我试着用一个值类型来解释它,比如Int:
过程1通过传递一个Int ByVal调用过程2。这个int在过程2的堆栈中有自己的内存,这意味着,改变P2中的这个值不会改变P1中的值,因为这两个值在每个堆栈中保存一次。
现在与byref相同:过程2不保存Int的副本,但可以直接访问该值。(在我看来)有两种可能使这一工作:
- int被打包在堆上,实际上有2个指针这个Int,但是由于它现在在堆上,所以可以看到值的变化
- P2对P1的栈有一定的访问权限,这意味着我想这是不可能的,因为这意味着
这样能更清楚地表达我的意思吗?
传递的参数是某个对象的地址。该引用与方法的所有其他参数一起在堆栈上传递。
实际对象本身存在于调用该方法之前的位置。它可以在堆栈中,也可以在堆中,都无所谓。通过引用传递对象的行为不会导致对象在内存中被移动,比如从堆栈移动到堆,或者从堆移动到堆栈。
虽然Servy已经正确地回答了这个问题,但是对于用ref
传递参数和按值传递对象的引用之间的区别,似乎有很多令人可怕的混淆。因此,我认为有必要提供一个简短的说明。
假设下面的简单类:
class Player
{
public Player(int health)
{
Health = health;
}
public int Health { get; set; }
}
我们现在可以测试更新对象的属性,也可以更改引用本身:
static void Main(string[] args)
{
Player player = new Player(100);
Console.WriteLine(player.Health);
ChangeHealth(player);
Console.WriteLine(player.Health);
ChangeHealthByRef(ref player);
Console.WriteLine(player.Health);
ChangePlayer(player);
Console.WriteLine(player.Health);
ChangePlayerByRef(ref player);
Console.WriteLine(player.Health);
}
static void ChangeHealth(Player player)
{
player.Health = 80;
}
static void ChangeHealthByRef(ref Player player)
{
player.Health = 60;
}
static void ChangePlayer(Player player)
{
player = new Player(40);
}
static void ChangePlayerByRef(ref Player player)
{
player = new Player(20);
}
输出:100
80
60
60
20
ChangeHealth
成功修改player
对象的Health
属性。ChangeHealthByRef
也成功地修改了player
对象的Health
属性。因此,您可以看到,在这两个调用中,player
所引用的对象都可以被修改,尽管ChangeHealth
使用了引用的副本。
现在,这是我认为人们感到困惑的部分:
ChangePlayer
创建一个新的Player
对象,该对象修改传入的引用的副本。这意味着更改不会反映在调用代码中(即Health
仍然= 60)。ChangePlayerByRef
也创建了一个新的Player
对象,但是,这一次,它是直接修改引用,这意味着的变化确实反映在调用代码中(即Health
= 20)。
看一下这个问题的答案。
是否int ref parameter得到框?
也许它能帮助你。
谢谢