方法的参数有六种,分别是值参数、引用参数、输出参数、参数数组、命名参数、可选参数。
值参数
值参数是方法的默认类型,通过复制实参的值到形参的方式把数据传递到方法,方法被调用时,系统作两步操作;
在栈中为形参分配空间。复制实参到形参。
1)在方法被调用前,用作实参的变量a1的引用已经在栈里了。
2)随着方法的开始,系统在栈中为形参分配空间,并从实参复制值。
3)因为a1是引用类型,所以引用被复制,结果实参和形参都引用堆中的同一个对象。
4)因为a2是值类型,所以值被复制,产生了一个独立的数据。
5)在方法执行后,形参被从栈中弹出。
6)a2、值类型,它的值不受方法行为的影响。
7)a1、引用类型,它的值被方法的行为改变了。
引用参数
使用引用参数时,必须在方法的声明与调用中使用ref修饰符。实参必须是变量,在用作实参前必须赋值。
对于值参数,系统在栈上为形参分配内存;相反,对于引用参数,形参的参数名看起来就好像是实参变量的别名,也就是说,它们指向的是相同的内存位置。所以在方法的执行过程中对形参作的任何改变,在方法执行完成后依然有效(表现在实参变量上)。
引用参数的传递,对值类型与引用类型都是完全传递,不存在复制值与复制引用,即引用相同的内存位置。
输出参数
输出参数用于从方法体内把数据传递到调用代码,它非常类似引用参数。
1,必须在方法的声明与调用中使用out修饰符。
2,和引用参数相似,实参必须是变量。
就像引用参数,输出参数的形参担当实参的别名,方法内对形参的任何改变在方法执行完成后,通过实参变量都可见。
与引用参数的不同,输出参数有以下2个要求。
在方法内部,输出参数在被读取之前必须被赋值,这意味着参数的初始值是无关的,因此没有必要在方法调用之前为实参赋值。在方法返回前,方法内部的任何贯穿的可能路径都必须为所有输出参数进行一次赋值。
参数数组
上面3中参数方式,必须严格的一个实参对应一个形参,参数数组不一样,它允许零个或多个实参对应一个特殊的形参。
参数数组的要求如下:
在一个参数列表中只能有一个参数数组。如果有,它必须是列表中的最后一个。
声明参数数组,必须要有params修饰符(调用不需要修饰符),必须是一种类型的数组。
使用分散式传参时,编译器做如下事:
1)接受实参列表,用它们在堆中创建并初始化一个数组。
2)把数组的引用保存到栈中的形参里。
3)如果在对应的形参数组的位置没有实参,编译器会创建一个有零个元素的数组来使用。
4)如果数组参数是值类型,那么值被复制,实参不受方法内部的影响。
5)如果数组参数是引用类型,那么引用被复制,实参引用的对象可以受到方法内部的影响。
在使用数组式传参时,编译器使用你的数据而不是重新创建一个。即相当引用参数。
命名参数
上面用到的四种参数,都是位置参数,也就是说每个实参的位置必须一一对应相应的形参位置。
从.Net4.0开始,只要显示指定参数的名字,就可以以任意顺序在方法调用中列出实参,细节如下。
1.方法的声明没有什么不一样。形参已经有名字了。
2.不过在调用方法的时候,形参的名字后面跟着冒号和实际的参数值或表达式。
在调用的时候,也可以位置参数和命名参数混合使用,但是所有的位置参数必须先列出,
可选参数
可选参数是.Net4.0才加入的,在调用方法的时候可以包含这个参数,也可以省略它。
为了表明某个参数是可选的,你需要在方法声明的时候为参数提供默认值。制定默认值的语法和初始化本地变量的语法一样。
如下图
1)形参b设置成了默认值。
2)因此,在调用方法的时候只有一个参数,方法会使用3作为第二个参数的初始化。
对于可选参数的声明,有几个重要事项:
1.不是所有的参数类型都可以作为可选参数。
1)只要值类型的默认值在编译的时候可以确定,就可以使用值类型作为可选参数。
2)只有在默认值是null的时候,引用类型才可以作为可选参数来使用。
3)可选参数只能是值参数。
2.所有必填参数必须在可选参数声明之前声明,如果有params参数,必须在所有可选参数之后声明。
3.必须从可选参数列表的最后开始省略,一直到开头,否则会造成参数歧义。
4.若想消除参数歧义,可以结合命名参数和可选参数的特性。
如下图
如果觉得《C#方法的六种参数 值参数 引用参数 输出参数 参数数组 命名参数 可选参数...》对你有帮助,请点赞、收藏,并留下你的观点哦!