引用/值参数在 C# 中的工作原理 [英] How parameter by reference/value works in C#
问题描述
我有这个示例代码:
public class MyClass
{
public int Value { get; set; }
}
class Program
{
public static void Foo(MyClass v)
{
v.Value = 2;
v = new MyClass();
v.Value = 3;
}
static void Main(string[] args)
{
var m = new MyClass();
m.Value = 1;
Foo(m);
Console.Write(m.Value);
Console.ReadLine();
}
}
我想知道为什么输出是 2 而不是 3,你能给我一些清楚的解释吗?
I would like to understand why the output is 2 and not 3, could you please give me some clear explanation?
谢谢
推荐答案
我将与您一起通过调试器一步一步地进行,我们将看到它是什么 2.
I will go through with you, step by step via the debugger and we will see what it is 2.
我们看到进入了Foo,我们通过引用传递了一个MyClass的实例v
(C#中的类实例默认是通过引用传递的)
We see that we entered into Foo and we passed an instance of MyClass by reference v
(class instances in C# are passed by reference by default)
在内存中,我们会看到这样的事情:
In memory, we would see something like this:
v = 0x01; //0x01 - is a simple representation of a pointer that we passed
v.Value = 1;
接下来,我们走过去,我们看到我们改变了引用中的值 Value.
next, we step over and we see that we change the value Value in our reference.
v = 0x01;
v.Value = 2; // our new value
然后我们将 new
分配给我们的 v
所以在内存中我们有
and then we assign new
to our v
so in memory we have
v* = 0x01 // this is our "old" object
v*.Value = 2;
v = 0x02 // this is our "new" object
v.Value = 3;
如您所见,我们的内存中有 2 个对象!新的 v
和旧的标有开始 v*
as you can see we have 2 objects in the memory! The new one v
and the old one marked with a start v*
当我们退出方法时,我们没有替换内存地址0x01
的内容,而是为函数的作用域创建了一个v
的本地副本,并且我们在内存地址 0x02
下创建了一个新对象,该对象未在 Main 方法中引用.
when we exit the method, we didn't replace the content of the memory address 0x01
but created a local copy of v
for the scope of the functions, and we created a new object under the memory address 0x02
which is not referenced in our Main method.
我们的主要方法是使用来自地址 0x01
的实例,而不是我们在 Foo 方法中创建的新 0x02
!
Our main method is using instance from address 0x01
not new 0x02
we created in Foo method!
为了确保我们传递了正确的对象,我们需要告诉 C# 我们想要编辑"使用 ref
输出或者我们想覆盖"使用 out
输出.
To make sure we pass the right object out, we need to tell C# that we want to either "edit" output using ref
or we want to "overwrite" output using out
.
在幕后,它们的实现方式相同!
Under the hood, they are implemented the same way!
不是将 0x01
传递给我们的 Foo 方法,而是传递 0x03
!它在 0x01
下有一个指向我们类的指针.所以当我们在使用ref
或out
的时候赋值v = new MyClass()
,实际上是在修改的值0x03
然后被提取并替换";在我们的 Main 方法中包含正确的值!
Instead of passing 0x01
to our Foo method, we pass 0x03
! which has a pointer to our class under 0x01
. So when we assign v = new MyClass()
when we use ref
or out
, we, in reality, modify the value of 0x03
which is then extracted and "replaced" in our Main method to contain the proper value!
这篇关于引用/值参数在 C# 中的工作原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!