引用/值参数在 C# 中的工作原理 [英] How parameter by reference/value works in C#

查看:50
本文介绍了引用/值参数在 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 下有一个指向我们类的指针.所以当我们在使用refout的时候赋值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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆