用户登录
用户注册

分享至

C#中引用类型的变量做为参数在方法调用时加不加 ref 关键字的不同之处

  • 作者: 最爱海贼王529
  • 来源: 51数据库
  • 2021-07-28

一直以为对于引用类型做为参数在方法调用时加不加 ref 关键字是没有区别的。但是今天一调试踪了一下变量内存情况才发现大有不同。

直接上代码,以下代码是使用了?ref 关键字的版本。它输出10。如果不使用ref 关键字则输出 1,2,3?

    class Program
    {
        static void Main(string[] args)
        {
            int[] myArray = new int[] { 1, 2, 3 };
            new SetClass().SetArray(ref myArray);
            /*
             不加ref关键字的引用类型传参情况                                    加上ref关键字后的引用类型传参情况
             &myArray                                                           &myArray
                0x000000c088d7e3d0                                                  0x0000008151b7e6b0
                *&myArray: 0x0000029b3f84ae00                                       *&myArray: 0x000001c5e5a7ae00
            */

            foreach (int i in myArray)
                Console.WriteLine(i);
            /*
             &myArray                                                           &myArray
                0x000000c088d7e3d0                                                  0x0000008151b7e6b0
                *&myArray: 0x0000029b3f84ae00                                       *&myArray: 0x000001c5e5a7ae00
            */
        }

    }

    class SetClass
    {
        //如果形参 array 是引用类型时(不论加不加 ref 关键字),则在方法执行时方法体内的局部变量 array 指向外部传进来的实参所指向的内存空间。
        //但是加上 ref 关键后在方法执行时方法体内接收传进来的实参时,并不会给 array 变量分配内存空间,即 变量array就是变量myArray。 
        internal void SetArray(ref int[] array)
        {
            /*
             &array                                                           &myArray
                0x000000c088d7e388                                                0x0000008151b7e6b0
                *&array: 0x0000029b3f84ae00                                       *&myArray: 0x000001c5e5a7ae00
            */
            array = new int[] { 10 };
            /*
             &array                                                            &myArray
                0x000000c088d7e388                                                 0x0000008151b7e6b0
                *&array: 0x0000029b3f84bbf0                                        *&myArray: 0x000001c5e5a7ae00
             */
        }
    }
}

一些说明:

  1. 以上代码中的注释可纵向分隔为两部分来看,左边部分是不加ref关键字调试时查看的内存情况,右边则是加上ref关键字后的情况。
  2. 每个/* */中注释都是代码执行完注释所在位置的上一语句后的内存情况。
  • ? ? ? ? ? ? ?&myArray? ? ? ? ? ? ? ? ? ? ? ? ?//表示获取这个变量内存的指令

? ? ? ? ? ? ? ? 0x000000c088d7e3d0? ? ? ? ? ? //表示这个变量在内存中的地址
? ? ? ? ? ? ? ? *&myArray: 0x0000029b3f84ae00? //表示这个变量指向的内存空间的对象的地址

  • ? ? ? ? 在visual studio 2019 中查看变量内存地址的方法:

? ? ? ? 方法一:
? ? ? ? 在即时窗口输入取地址符+变量名如 &a 这是会输出如下 两行:
? ? ? ? 0x000000325637e570
? ? ? ? *&a: 0x00000209ba0dad58
? ? ? ? 第一行 0x000000325637e570 代表变量本身的内存地址,第二行 *&a: 0x00000209ba0dad58 表示变量指向的对象的内存地址

? ? ? ? 方法二:
? ? ? ? 【调试】-【窗口】-【内存】-从列出来的4个中选一个,然后会调出内存查看窗口。在内存查看地窗口中的【地址】里输入[取地址符]+[变量名]如 &a ,这时地址中的&a会变成变量的十进制表示的内存地址,如:0x000000325637E570

?

补充几张调试中断在不同语句时的一些内存情况截图:(加上ref关键字后的引用类型传参情况图)

1.

2.

3.

4.


?

软件
前端设计
程序设计
Java相关