27

C# 之 方法参数传递机制_C#_Czhenya-CSDN博客

 4 years ago
source link: https://blog.csdn.net/Czhenya/article/details/104914423?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C# 之 方法参数传递机制

根据参数传递机制的不同,C#方法的形式参数分为四种:值形参、引用形参、输出形参以及形参数组,通过在形参定义时添加不同的参数描述符来表示。

一、值形参:(值类型形式参数)
声明时不带修饰符的形参是值形参。
一个值形参对应于方法的一个局部变量,只是它的初始值来自该方法调用所提供的相应实参。
当形参是值形参时,要求方法调用中的对应实参必须可以隐式转换为形参的类型。

看一个交换数的例子,当执行Exchange方法,Main中的a和b并没有收到影响:

 	class Program
    {
        static void Main(string[] args)
        {
            int a = 3, b = 5;
            Console.WriteLine("Main.. a:" + a + "...b:" + b);
            Exchange(a, b);
            Console.WriteLine("Main.. a:" + a + "...b:" + b);
        }

        static void Exchange(int a, int b)
        {
            Console.WriteLine("Exchange.. a:" + a + "...b:" + b);
            int temp = a;
            a = b;
            b = temp;
            Console.WriteLine("Exchange.. a:" + a + "...b:" + b);
        }
    }
结果

二、引用形参(ref关键字)
用ref 修饰符声明的形参是引用形参。
引用形参所表示的存储位置就是方法调用时给出的那个实参的存储位置。
当形参为引用形参时,方法调用中的对应实参必须由关键字ref并后接一个与形参类型相同的变量组成。变量在可以作为引用形参传递之前,必须先明确赋值。

同样是上面示例中的代码我将方法参数使用ref修饰,看下结果:此时的Main方法中的a和b的值也发生了转换.

	class Program
    {
        static void Main(string[] args)
        {
            int a = 3, b = 5;
            Console.WriteLine("Main.. a:" + a + "...b:" + b);
            Exchange(ref a,ref b);
            Console.WriteLine("Main.. a:" + a + "...b:" + b);

            Console.ReadKey();
        }

        static void Exchange(ref int a,ref int b)
        {
            Console.WriteLine("Exchange.. a:" + a + "...b:" + b);
            int temp = a;
            a = b;
            b = temp;
            Console.WriteLine("Exchange.. a:" + a + "...b:" + b);
        }
    }
结果
也就是说,当我们使用引用形参时,多个名称会表示同一存储位置。

三、输出形参 (out关键字)
用out修饰符声明的形参是输出形参。
输出形参所表示的存储位置就是在该方法调用中作为实参给出的那个变量所表示的存储位置。
使用方式和引用参数差不多一个使用ref关键字修饰,一个使用out关键字修饰,区别在于引用参数需要在方法调用前赋值,而输出参数在方法调用后,返回之前赋值

举个栗子:

 	class Program
    {
        static void Main(string[] args)
        {
            int[] arr = new int[5] { 1, 2, 3, 4, 5 };
            float average;
            int sum = Calculation(arr, out average);
            Console.WriteLine("这组数的和是:" + sum + "..平均数是:" + average);
            Console.ReadKey();
        }

        static int Calculation(int[] arr,out float average)
        {
            int sum = 0;
            for (int i = 0; i < arr.Length; i++)
            {
                sum += arr[i];
            }
            average = sum / arr.Length;
            return sum;
        }
    }
结果
输出参数可用于从方法向调用者传递数据。

四、形参数组 (引用类型形式参数)
当方法参数传递的类型为引用类型时,对参数中的值进行修改,就是对原变量进行修改,也就是说引用类型传递参数时,传递进去的是地址.

举个栗子:修改参数数组中的值,原数组也会被修改,看代码:

 	class Program
    {
        static void Main(string[] args)
        {
            int[] arr = new int[5] { 1, 2, 3, 4, 5 };            
            Console.WriteLine("Main 调用方法前:");
            for (int i = 0; i < arr.Length; i++)
            {
                Console.Write(arr[i] + " ");
            }
            Console.WriteLine();
            Reference(arr);
            Console.WriteLine();
            Console.WriteLine("Main 调用方法后:");
            for (int i = 0; i < arr.Length; i++)
            {
                Console.Write(arr[i] + " ");
            }

            Console.ReadKey();
        }

        static void Reference(int[] arr)
        {
            Console.WriteLine("Reference 传进来:");
            for (int i = 0; i < arr.Length; i++)
            {
                Console.Write(arr[i] + " ");
            }        
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i] = 0;
            }
            Console.WriteLine();
            Console.WriteLine("Reference 修改后:");
            for (int i = 0; i < arr.Length; i++)
            {
                Console.Write(arr[i] + " ");
            }
        }
    }
结果

C#中的位置参数和命名参数

位置参数:进行方法调用时,每个实参的位置都必须一一对应相应形参的位置,这种参数叫做位置参数,我们上面例子中使用的都是位置参数。
从C#4.0开始,方法调用时支持命名参数机制,只要显式指定参数的名称,就可以以任意顺序在方法调用中列出实参。

我将1例的代码修改了一下调用的形式,大概是这样:

	class Program
    {
        static void Main(string[] args)
        {
            int a = 3, b = 5;
            Console.WriteLine("Main.. a:" + a + "...b:" + b);
            //Exchange(a, b);
            Exchange(b: b, a: a);
            Console.WriteLine("Main.. a:" + a + "...b:" + b);

            Console.ReadKey();
        }

        static void Exchange(int a,int b)
        {
            Console.WriteLine("Exchange.. a:" + a + "...b:" + b);
            int temp = a;
            a = b;
            b = temp;
            Console.WriteLine("Exchange.. a:" + a + "...b:" + b);
        }
    }

可能这个例子写的不太好,不应该将形参和实际变量名起重复的名字,不过这个并影响功能,由下图可以看出当我选中形参中的a时,方法中的a都会被标识出来,表示是同一个变量,此时Main方法中的a:a也被标识出来了,那么说明他和这个形参也是同一变量
参数
PS:命名参数,可以明确知道是那个变量赋值个了那个参数,这使得方法调用时具有更多的参数时不容易出错,增加代码的可读性。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK