不得不聊的关于方法的参数的那些事儿

  很多朋友在看了这个标题之后,可能会以不屑的眼神看着我说,"去,我xx年的编程经验,难道方法(函数)还有什么不知道的么?你可要记住,从我开始学编程的那1天起就已经开始每天都在写方法了."  当然我不会从最基本的说起,更多的我希望说说我自己的的理解以及原理,所以这篇文章仅仅是个人总结,可能会由于个人知识面比较窄的原因会存在一些瑕疵,请大家不吝指教.好了,那我们就开始吧.

     

 

 

  a. 为什么定义了形参,就一定要传递实参?

  谁都知道,如果1个方法定义了参数,那么我们在调用这个方法的时候,就必须要为这个方法的参数赋值.比如下面这样.

           

   如果不传递的话,谁都知道这将是1个什么样的后果.

    

   但是又有谁想过为什么是这样的呢?为什么方法定义了参数,我们在调用的时候就必须要为其传递实参呢?反正之前我是没有想过这个问题的,仅仅是这样的1句话就将自己打发,"那是微软规定的语法". 后来仔细想了一下,我认为之所以是这样,是因为方法的参数本质上是这个方法的1个局部变量.所以我们可以在方法中直接使用这个参数,并且你也不能再这个方法中定义1个名字和参数的名字相同的变量.我们说将实参传递给形参实际上就是将实参的值赋值给形参的1个过程.而局部变量有1个最重要的特点就是使用之前必须赋值.但是我们在声明这个参数的时候却没有为它赋值,仅仅是声明了而已.所以如果调用者要执行这个方法中的代码,而在这个方法中是有可能会用到这个参数的.所以要求调用者在调用方法的时候必须要为形参赋值.

  对于方法的参数的本质是方法的局部变量这1个说法,估计有童鞋会有意见.

    

    正如上面这段代码.你会发现我们在这里可以直接使用参数,但是参数是没有值的.这个时候是不会报错的(使用了未赋值的局部变量).原因很简单.因为方法中的代码只有在方法被调用的时候才会执行,而这个方法如果被调用,那么调用者就必须要为参数传值,所以当这个方法中的代码运行起来以后,参数str中绝对肯定已经有值了.

  所以我们的结论是: 方法的参数本质上是这个方法的局部变量,而局部变量在使用之前必须要有值.而我们在声明形参的时候没有为形参赋值,所以要求调用者在调用的时候必须赋值,如果不赋值的话,在方法中使用到形参的时候会因为形参没有被赋值而报错.

  b.方法的参数的默认值.

  从上面我们可以知道,之所以一定要为形参传递参数是因为形参没有值.那如果是因为这样话我们可以不可以在声明形参的同时就为这个形参赋1个默认值呢?答案当然是肯定的.原因嘛很简单,刚才才说了 定义1个方法的参数其实就是声明了1个方法的局部变量,那我当然可以在声明这个局部变量的同时为这个局部变量赋值了.

    

    这个时候,我们发现我们在声明方法的参数的同时为这个参数赋了1个默认值,那就意味着这个局部变量已经有值了,如果调用者希望执行这个方法中的代码,大可不必一定要为这个方法的参数传值.完全可以不传值.方法仍然会执行,不会报错.再一次证明了方法的参数的本质是这个方法的1个局部变量.

    当然了,如果我们在调用带默认值的参数的方法的时候,不传值的话,在方法的内部会直接使用其默认值.如果调用者希望这个值是自己指定的值,那么就只有选择自己传递了.

   

  所以,我的总结是:如果方法的参数的值不一定要求调用者指定,就可以为这个参数指定默认值,调用者根据具体的情况来选择传递还是不传递.如果调用者希望这个参数使用默认值那么就可以选择不传递,如果不希望使用默认值而是调用者自己指定,就自己选择为参数传递值.

  在为方法定义带默认值的参数的时候必须要注意第1个问题.所有的带默认值的参数必须出现在参数列表的最右侧.换句话说,带默认值的参数必须出现在参数列表的最后面.

   

   我们将带默认值的参数放在参数列表的最右侧,才可以滴.原因很简单.我想不解释了吧.因为编译器不知道我们到底是要给那1个形参传递参数.

  关于方法的参数的默认值注意的第2个问题:参数的默认值必须是编译时就可以确定的值.如果我们为参数的默认值赋值1个运行时才确定的变量的话,那么这个时候编译器是会报语法错误的.

   

  第3个要注意的问题:ref/out修饰的参数不能有默认值,那关于这个的原因,我想应该不难理解.因为ref/out要求传递变量的地址,而不是变量的值,所以就算可以给值也是没有任何实际意义的.

   

   第4个要注意的问题: params修饰的数组参数仍然需要放在参数列表的最后,而不是放在默认值参数的最前面.

     

   c. 显示的为形参传递实参.

    正如我们前面所说,方法的参数可以有默认值,它的好处在于可以不给带默认值的参数传递实参,但是很快我们发现1个困扰我们的问题了.

    

    看看上面这个方法,假如我们作为调用者只希望给形参str赋值,我们该如何传参呢?我们试着这样调用.

    

    我们却发现,它将字符串"testString"传递给了形参name,原因很简单嘛。我们知道在传递参数的时候,编译器会按照顺序将实参1个1个的赋值给形参,所以不奇怪的将实参"testString"赋值给了第3个形参.

    那到底该如何解决呢? 不急,先带大家看1下我们经常看见的1个现象,但是很少去深究,起码我之前是这样的.当我们在调用1个方法的时候,并为这个方法的参数传递实参的时候,Visual Studio会做如下提示:

    

    这个时候VS自动提示的name:是个什么东西呢?以前也有朋友问过我这个问题,当时我支支吾吾半天没说出个所以然.现在总算搞清楚了,这个其实就是方法的形参名.通过方法的形参名我们可以指定为那1个形参赋值,看下面的代码吧.

   

   这个时候你会发现,程序运行的时候,不再是按照顺序将实参的值赋值给形参了,而是根据我们指定的形参来赋值的了.这样就可以解决我们之前的那个问题了.

   好了,今天就到这里了.对于一些大牛而言,可能这些东西早已知晓,本人在园子里发这篇博文也是希望给自己做1个小的总结.难免会有纰漏,请大家指点.

posted @ 2013-07-16 16:28  highven  阅读(1718)  评论(18编辑  收藏  举报