ref传递

下面通过一个排序的小栗子来分析ref传递:

        static void Main(string[] args)
        {
            int [] arr=new int[]{1,23,44,56,90};
            int num;
            Console.WriteLine("请输入您想插入的数据:");
            if (int.TryParse(Console.ReadLine(), out num))
            {
                InsertValue( arr,num);
            }
            Console.WriteLine("-----------------------");
            foreach (int a in arr)
            {
                Console.WriteLine(a);
            }
            Console.ReadKey();
        }

        /// <summary>
        /// 将制定数据插入到指定数组中
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="num"></param>
        static void InsertValue(  int[] arr1, int num)
        {

            //1.将数组扩容
            int[] newArr = new int[arr1.Length + 1];
            arr1.CopyTo(newArr,0);
            //2.将数组重新引用
            arr1 = newArr;
            //3.获得插入位置
            int position=0;
            for (int i = 0; i < arr1.Length; i++)
            {
                if (num < arr1[i])
                {
                    position = i;
                    break;
                }
            }
            //4.将数据重新排列
            for (int i = arr1.Length - 1; i > position; i--)
            {
                arr1[i] = arr1[i - 1];
            }
            arr1[position] = num;
        }

这样输出的结果是:

显然我们的要插入的数据没有插进去,换句话说就是它输出的是原始的数组。对于数组的存储,数组名存储在栈空间,具体数组数据存储在堆空间,通过即时窗口可以看到:

即需要输出的数组arr的堆空间没有改变,所以输出的还是原始的没有插入数据的数组,这里其实应该改变为0x02332bc4,因为插入一个数据后的地址是0x02332bc4

ref关键字通过引用传递参数,通过引用传递的效果是,对所调用方法中的参数进行的任何更改都反映在调用方法中,但是使用ref传递的实参必须先初始化。

所以,这里我们可以在定义InsertValue时这样做: static void InsertValue( ref int[] arr1, int num),然后使用时:InsertValue(ref arr,num);就可以达到我们的效果了。

无论方法参数是值类型还是引用类型,均可由ref修改,当通过引用传递时,不会对值类型装箱(装箱即将值类型转换为引用类型)。

原文地址:https://www.cnblogs.com/miaoying/p/5098643.html