(教学思路 C#之类三)方法参数类型(ref、out、parmas)

这节课我们来学习方法中的参数传递,在面向对象二中,我曾说过,参数也属于变量的一种,在c语言的学习时,同学们都学习过参数这个概念和用法,方法使用参数列表来传递变量的基本语法如下:
returnType  FunctionName(paraType1  paraName1,paraType2  paraName2,……)
{
   Function body;
}
其中的returnType是指方法的返回值,FunctionName指方法的标识符,paraType1指参数1的数据类型,paraName1是参数1的标识符,调用这种类型的方法的时候,必须传入与类型paraType1相符的参数值,并且传入的参数个数也必须相符,方法内部以参数名称paraName1来识别。
     在C#中,参数一共四种形式:分别是

参数类型值参数
引用参数--ref
输出参数--out
动态参数--parmas


       他们都有什么区别呢?具体怎么用呢?我们现在就开始具体的讲解,
值参数


 

         值参数就是参数的是值类型的,如 int   add(int i,int j){},i和j就是值参数,值参数很好理解,我们也经常用到,下面的代码实例主要是为了对比引用参数和输出参数的区别的实现两个数值交换的例子,请同学们体会它们的不同。

值参数传参实例

 

运行结果

请输入整数a=2
请输入整数b=4

值参数方法进来时,a=2  b=4

经过值参数交换方法交换后,a=4  b=2

采用值参数交换方法后,Main方法中现在为a=2

经过值参数交换方法后,Main方法中现在为b=4
请按任意键继续. . .

 

可以看出值参数经过方法传递后,初值是不改变的,下面我们来看一下引用参数。

引用参数


 

      如果方法的参数为数值类型时,则传递的方式主要分为两种:传值和传址。这两种方式最大的差异在于:当一个参数以传值的方式传递时,变量的值即使在方法中被改变,它本身还是维持一开始传入的值,我们刚才学习的值参数就是传值方式;而以传址方式传入的变量,当方法将其改变的时候,此变量的值便永远被更改,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作为引用参数传址传递的区别:

值参数与引用参数的区别
运行结果

请输入整数a=2
请输入整数b=4

参数进来时,a=2  b=4

方法交换后,a=4  b=2

采用值参数传递交换方法后,结果应该和初值相同,Main方法中现在为a=2

经过引用参数传递交换方法后,结果应该和出方法时的值相同,Main方法中现在为b=2
请按任意键继续. . .

    很明显看出,Main方法中b的值变化了,和出方法时的值相同,而a因为是传值传递,仍然是初值。参数是数值型的传址传递还有一种就是使用out关键字,那么它与ref有什么不同呢?

输出参数


      输出参数传址时,要使用out关键值,out关键字允许我们以一个未初始化的变量作为参数,直接传入方法当中,在方法结束的时候,指定所要返回的值给它,而使用ref关键字传给方法之前,必须将一个数值传入到方法中,out关键字在某种程度上来说,有点像return的功能,就是把方法的结果返回到调用这个方法的主方法中,使用out关键字要注意到:主方法中传入调用的方法的out参数值应该为未初始化的,即使你初始化了,初始化的值也相当于不存在。我们来看这个例子,体会一下out的用法。

比较out和return的用法

 

运行结果

请输入正方形的边长bc=4

正方形的面积mj=16
=================
使用returnQMJ方法面积mj=16
请按任意键继续. . .

       这个例子我主要是想告诉大家使用out能够达到和return返回值一样的功能效果。

       下面我们来看一下为什么加了ref和out关键字后,主方法中的数值会改变呢?这主要是因为存放参数的内存机制发生了变化而引起的。上面的3个例子都是数值类型作为参数,但是因为第二、三例子中加入了ref和out关键字,改变了数值类型按值传递的特性,改为按照传递在内存中存放的地址,按地址传递后参数的值会改变的原因就在此,因为按内存地址传递时,调用方法的参数在定义时,不会因为参数是数值类型而在线程堆栈中开辟新的空间来存放新的值,而是会在线程堆栈中存放一个指向主方法定义的变量(初值)的内存地址,当这个地址指向的内存值因为调用方法中对参数的作用(如交换,如平方)后,内存中的值就改成了调用方法作用后的值,这样在打印主方法的变量时,值自然就改成了调用方法后的值了。

       接下来我们来看一个参数为引用类型的实例,因为参数本身就是引用类型(string类型除外),所以这种参数传递属于传址传递:

数组为参数的传址传递

运行结果:

数值参数传入时,数组中的每个元素值是:
1  2  3
改变后,方法内部的数组a中的每个元素值是:
2  4  6
经过方法后,Main方法中数组a的每个元素值是:
2  4  6  请按任意键继续. . .

      通过这个实例,同学们应该看出引用类型作为参数时,也会影响主方法中带入到调用方法的值。下面我们来学习最后一直参数类型叫做动态传参。

动态传参


 

      动态传参主要是指参数的个数可以根据需要改变,使用动态传参要用到parmas关键字,它的具体用法我们来看这个例子:

动态传参实例1

 对照一下上个例子和本例,我们会发现,动态传参,不必规定数组的个数,而是根据需要使用,本例结果如下:

数值参数传入时,数组中的每个元素值是:
1  2  3  4
改变后,方法内部的数组a中的每个元素值是:
2  4  6  8
请按任意键继续. . .
 

    现在我们来做下一个例子,就是调用方法中有两个参数,一个int型,一个动态的数组类型parmas int[],要告诉大家的是,如果使用parma动态参数,动态参数一定只有一个,必须当有多个参数时,动态参数的位置在最后,我们把上面的例子修改一下,大家体会一下不同。

动态传参实例2

 

运行结果

数值参数传入时,数组中的每个元素值是:
2  3  4  k=1

改变后,方法内部的数组a中的每个元素值是:
4  6  8  k=1

请按任意键继续. . .

       可以看出因为把parmas的动态参数放到了最后,编译器就自动的把第一个值1直接给了k,把剩下的2,3,4给了数值a参数带入到方法中,所以使用parmas一定要注意到这个问题。

       本节课我们就学习到这里,下一节我们要来学习一下类四:构造方法、析构方法

posted @ 2011-11-01 17:03  星月磊子  阅读(255)  评论(0编辑  收藏  举报