如果方法的参数为数值类型时,则传递的方式主要分为两种:传值和传址。这两种方式最大的差异在于:当一个参数以传值的方式传递时,变量的值即使在方法中被改变,它本身还是维持一开始传入的值,我们刚才学习的值参数就是传值方式;而以传址方式传入的变量,当方法将其改变的时候,此变量的值便永远被更改,C#默认以传值方式传递参数,如果要使用传址方式传递,就需要用到下面我要说的理论。数值类型一律是以传值方式进行传递的,如果要改变这种行为,用传址方式传递参数,必须使用ref和out关键字进行修饰,当然如果参数本身就是引用类型的(string类型除外),不需要加ref和out关键字,他们的传递也是采用传址方式的.
使用ref关键字修饰的引用参数传递的方法书写格式如:static int add(ref int i,ref int j){} .在参数数值类型的前面加入ref修饰,在调用这个方法时,传入的参数前也必须加ref关键字,如:add(ref a,ref b);
下面我们上面的例子中Exchange方法中参数b变成ref形式,同学们来体会一下a作为值参数传值传递和b作为引用参数传址传递的区别:
值参数与引用参数的区别
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
1class Class2
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
2 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
3
//定义一个交换两个数的值的一个方法Exchange ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
4
//此处请注意,本方法使用了static关键字,原因是:根据我们类一所提到的,如果是实例方法(不加static关键字), ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
5
//必须通过类的对象来调用,即使在同一个类中,加入static关键字后,静态成员就属于类的引用范围了, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
6
//因为在一个类中,所以不必类名.,在其他方法中直接就可以调用这个方法。对比下面的实例方法 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
7
static void Exchange(
int a,
ref int b)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
8 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
9 Console .WriteLine ();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
10 Console.WriteLine(
"参数进来时,a={0} b={1}", a, b);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
11
int c = 0;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
12 c = a;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
13 a = b;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
14 b = c;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
15 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
16 Console.WriteLine(
"方法交换后,a={0} b={1}", a, b);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
17 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
18
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
19 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
20
//看这个实例方法,对照上一个方法,看在main方法中的调用是不同的, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
21
//此方法必须通过Class2的对象s.来调用,而上一个方法是直接调用(因为在一个类中,省略了类名.来调用) ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
22
void Exchange1()
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
23 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
24 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
25
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
26
static void Main()
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
27 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
28
//输入初值 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
29 Console.Write(
"请输入整数a=");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
30
int a =
int.Parse(Console .ReadLine());
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
31
//输入初值 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
32 Console.Write(
"请输入整数b=");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
33
int b =
int.Parse(Console.ReadLine());
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
34
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
35
//观察1:经过交换后a和b的结果的变化,(方法结束时交换了a和b的值) ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
36
//2:对比下面的调用,记住静态方法调用的方式 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
37
//3:main方法结束前,我们再次打印main中定义的a和b的值的变化:a和初值相同,b与出方法值相同 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
38 Exchange(a,
ref b);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
39
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
40
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
41
//对比上面的调用,记住实例方法调用的方式 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
42 Class2 s =
new Class2();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
43 s.Exchange1();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
44
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
45
//因为是值参数的传递方法,不会改变Main方法中的a的值,结果应该和初值相同 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
46 Console.WriteLine(
"采用值参数传递交换方法后,结果应该和初值相同,Main方法中现在为a=" + a);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
47 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
48
//因为是引用ref参数的传递方法,会改变Main方法中的b的值,结果应该和出方法时的值相同 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
49 Console.WriteLine(
"经过引用参数传递交换方法后,结果应该和出方法时的值相同,Main方法中现在为b=" + b);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
50 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
51 }
很明显看出,Main方法中b的值变化了,和出方法时的值相同,而a因为是传值传递,仍然是初值。参数是数值型的传址传递还有一种就是使用out关键字,那么它与ref有什么不同呢?
输出参数
输出参数传址时,要使用out关键值,out关键字允许我们以一个未初始化的变量作为参数,直接传入方法当中,在方法结束的时候,指定所要返回的值给它,而使用ref关键字传给方法之前,必须将一个数值传入到方法中,out关键字在某种程度上来说,有点像return的功能,就是把方法的结果返回到调用这个方法的主方法中,使用out关键字要注意到:主方法中传入调用的方法的out参数值应该为未初始化的,即使你初始化了,初始化的值也相当于不存在。我们来看这个例子,体会一下out的用法。
比较out和return的用法
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
1class Class2
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
2 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
3
//定义一个求正方形面积的方法,传入正方形的边长,返回正方形的面积 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
4
static void QMJ(
double bc,
out double mj)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
5 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
6 mj = bc * bc;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
7 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
8
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
9
//对比使用return返回面积的方法,达到的效果是一样的 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
10
static double returnQMJ(
double bc)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
11 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
12
return bc * bc;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
13 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
14
static void Main()
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
15 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
16 Console.Write(
"请输入正方形的边长bc=");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
17
double bc =
double.Parse(Console.ReadLine());
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
18 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
19
//传入QMJ方法的mj是为赋初值的 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
20
double mj;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
21
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
22
//通过方法调用,改变mj的值为出方法的值,打印出来,bc的值不变 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
23 QMJ(bc,
out mj);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
24 Console.WriteLine(
"正方形的面积mj="+mj);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
25
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
26 Console.WriteLine(
"=================");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
27
//使用return方式,返回方法的结果值 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
28 Console.WriteLine(
"使用returnQMJ方法面积mj="+returnQMJ(bc));
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
29 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
30 }
这个例子我主要是想告诉大家使用out能够达到和return返回值一样的功能效果。
下面我们来看一下为什么加了ref和out关键字后,主方法中的数值会改变呢?这主要是因为存放参数的内存机制发生了变化而引起的。上面的3个例子都是数值类型作为参数,但是因为第二、三例子中加入了ref和out关键字,改变了数值类型按值传递的特性,改为按照传递在内存中存放的地址,按地址传递后参数的值会改变的原因就在此,因为按内存地址传递时,调用方法的参数在定义时,不会因为参数是数值类型而在线程堆栈中开辟新的空间来存放新的值,而是会在线程堆栈中存放一个指向主方法定义的变量(初值)的内存地址,当这个地址指向的内存值因为调用方法中对参数的作用(如交换,如平方)后,内存中的值就改成了调用方法作用后的值,这样在打印主方法的变量时,值自然就改成了调用方法后的值了。
接下来我们来看一个参数为引用类型的实例,因为参数本身就是引用类型(string类型除外),所以这种参数传递属于传址传递:
数组为参数的传址传递
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
1class Class2
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
2 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
3
//定义一个静态的方法,参数是引用类型的数组参数a, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
4
//方法内部的功能是,改变数值a中每个元素的值,让改变后的值是原来的2倍 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
5
static void ArrayMethod(
int [] a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
6 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
7 Console.WriteLine(
"数值参数传入时,数组中的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
8
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
9 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
10 Console.Write(i+
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
11 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
12 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
13
//改变数值a中每个元素的值,让改变后的值是原来的2倍 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
14
for (
int j = 0; j < a.Length; j++)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
15 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
16 a[j] = a[j] * 2;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
17 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
18 Console.WriteLine(
"改变后,方法内部的数组a中的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
19
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
20 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
21 Console.Write(i +
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
22 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
23 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
24 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
25
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
26
static void Main()
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
27 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
28
//给数值a赋初值 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
29
int[] a =
new int[] {1,2,3 };
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
30
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
31
//调用方法将引用类型的数组参数a带入方法中 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
32 ArrayMethod(a);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
33
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
34
//经过方法后引用类型的数组参数a的元素值应该发生改变, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
35 Console.WriteLine(
"经过方法后,Main方法中数组a的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
36
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
37 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
38 Console.Write(i +
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
39 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
40 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
41 }
运行结果:
通过这个实例,同学们应该看出引用类型作为参数时,也会影响主方法中带入到调用方法的值。下面我们来学习最后一直参数类型叫做动态传参。
动态传参
动态传参主要是指参数的个数可以根据需要改变,使用动态传参要用到parmas关键字,它的具体用法我们来看这个例子:
动态传参实例1
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
1
class Class2
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
2 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
3
//定义一个静态的方法,参数是引用类型的数组参数a,采用动态传参方式, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
4
//方法内部的功能是,改变数值a中每个元素的值,让改变后的值是原来的2倍 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
5
static void ArrayMethod(
params int [] a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
6 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
7 Console.WriteLine(
"数值参数传入时,数组中的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
8
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
9 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
10 Console.Write(i+
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
11 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
12 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
13
//改变数值a中每个元素的值,让改变后的值是原来的2倍 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
14
for (
int j = 0; j < a.Length; j++)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
15 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
16 a[j] = a[j] * 2;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
17 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
18 Console.WriteLine(
"改变后,方法内部的数组a中的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
19
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
20 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
21 Console.Write(i +
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
22 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
23 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
24 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
25
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
26
static void Main()
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
27 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
28
//使用了动态传参,我们可以不规定数组的大小,按照需要进行传入。 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
29 ArrayMethod(1,2,3,4);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
30
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
31 /**
/////给数值a赋初值 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
32
//int[] a = new int[] { 1, 2, 3 }; ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
33
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
34 /**
/////调用方法将引用类型的数组参数a带入方法中 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
35
//ArrayMethod(a); ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
36
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
37
//经过方法后引用类型的数组参数a的元素值应该发生改变, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
38
//Console.WriteLine("经过方法后,Main方法中数组a的每个元素值是:"); ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
39
//foreach (int i in a) ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
40
//{ ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
41
// Console.Write(i + " "); ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
42
//} ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
43 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
44 }
对照一下上个例子和本例,我们会发现,动态传参,不必规定数组的个数,而是根据需要使用,本例结果如下:
现在我们来做下一个例子,就是调用方法中有两个参数,一个int型,一个动态的数组类型parmas int[],要告诉大家的是,如果使用parma动态参数,动态参数一定只有一个,必须当有多个参数时,动态参数的位置在最后,我们把上面的例子修改一下,大家体会一下不同。
动态传参实例2
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
1class Class2
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
2 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
3
//定义一个静态的方法,参数是引用类型的数组参数a,采用动态传参方式, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
4
//方法内部的功能是,改变数值a中每个元素的值,让改变后的值是原来的2倍 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
5
static void ArrayMethod(
int k,
params int [] a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
6 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
7
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
8 Console.WriteLine(
"数值参数传入时,数组中的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
9
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
10 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
11 Console.Write(i+
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
12 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
13 Console.WriteLine(
"k="+k);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
14 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
15
//改变数值a中每个元素的值,让改变后的值是原来的2倍 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
16
for (
int j = 0; j < a.Length; j++)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
17 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
18 a[j] = a[j] * 2;
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
19 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
20 Console.WriteLine(
"改变后,方法内部的数组a中的每个元素值是:");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
21
foreach (
int i
in a)
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
22 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
23 Console.Write(i +
" ");
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
24 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
25 Console.WriteLine(
"k="+ k);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
26 Console.WriteLine();
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
27 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
28
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
29
static void Main()
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
30 {
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
31
//使用了动态传参,我们可以不规定数组的大小,按照需要进行传入。 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
32
//如果调用方法把parma参数写在前面,因为它的个数是不固定的, ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
33
//她会把最后一个值,也当成是数组中元素进行操作。 ![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
34 ArrayMethod(1,2,3,4);
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
35
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
36
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
37 }
![(教学思路 C#之类三)方法参数类型(ref、out、parmas)_ref](https://s2.51cto.com/images/editer/InBlock.gif)
38 }
可以看出因为把parmas的动态参数放到了最后,编译器就自动的把第一个值1直接给了k,把剩下的2,3,4给了数值a参数带入到方法中,所以使用parmas一定要注意到这个问题。
本节课我们就学习到这里,下一节我们要来学习一下类四:构造方法、析构方法