傻瓜教你学实参和形参,命名参数,可选参数
应一园友的要求今天抽空在这唠唠形参和实参
其实形参和实参是个非常简单的话题,说白了
"形参"就是在方法声明的时候,作为方法签名的一部分,也就是我们所说的"参数列表"里面的部分,例如public static void ShowMsg(string name){}
此处的name就是形参,简单吧,其实"形参"也就是对一个变量的定义,所以要有类型(string),还要有变量名(name),和我们在方法体里所定义的变量差不多,区别就在于我们的形参必须在方法被执行之前被赋值(初始化),因为它相当于一个局部变量,局部变量必须在使用前就要有值,要不然没法用呀,而且还是在外面被赋值,out参数除外
形参就是那么简单,再来说说"实参",其实它就是一个用来初始化形参的"表达式或者变量",对于"值参数"可以使表达式,但是对于"引用参数和输出参数"就不能是表达式了,只能是变量,实参它是放在调用方法的圆括号内的,例如string nameStr="李杰";ShowMsg(nameStr);此时的ShowMsg()中的nameStr就是实参,它是专门用来初始化形参的,所以每一个实参都要与其"对应的形参"类型一致,或者能够"隐式的"转换为形参的类型,一般说来实参和形参都是要一一对应的,这种一一对应的参数我们通常称为"位置参数",说到这你肯定能猜到必然还会有其他形式的参数,没错,还有'命名参数'和'可选参数',为什么我把命名参数和可选参数不和值参数他们一起说呢,主要是想体现出和"位置参数中一一对应"的区别,
下面我就来说说命名参数,很简单,命名参数肯定是给某个参数命个名字,那到底是给什么参数命名呢?
其实就是给"实参"命个名让它能给形参形成映射从而能够为每一个形参初始化,例如我们上面的程序可以改下
private static void ShowMsg(string name, string nickName) { Console.WriteLine("我的名字:{0},昵称:{1}", name, nickName); } static void Main(string[] args) { string nameStr = "李杰"; string nickNameStr = "小Ai"; ShowMsg(nickName:nickNameStr,name:nameStr);//此时我们颠倒了原来实参的位置,将"姓名"放在了后面 Console.ReadKey(); }
但是形参的是"姓名"在前,颠倒了实参中的位置,会导致初始化的形参也颠倒了,那怎么样我们才能颠倒实参同时也给形参赋了正确的值呢,此时我们就是使用"命名参数"的形式,给实参起名字,但是"这个名字很有讲究",它就是形参的变量名,你要把值传给哪个变量名,就在调用方法时使用"形参变量名:实参值"的形式,这种形式我个人并不经常用,除非你是想让别人很清楚的知道你的这个实参值是传给哪个形参的,用于干嘛的,例如,我们在计算"一个长方形的面积时就可以使用命名参数的形式",告诉别人你传过去的哪个是"长",哪个是"宽"
有了命名参数,还有一种就是"可选参数",它同样是针对实参而言的,'可选'意思就是你可传这个参数,也可不传,它声明方法的时候,参数列表和先前的有点不一样
private static void ShowMsg(string name, string nickName="小Ai") { Console.WriteLine("我的名字:{0},昵称:{1}", name, nickName); } static void Main(string[] args) { string nameStr = "李杰"; string nickNameStr = "杰哥"; ShowMsg(nameStr);//输出我的名字:李杰,昵称:小Ai ShowMsg(nameStr,nickNameStr);//输出我的名字:李杰,昵称:杰哥 Console.ReadKey(); }
和先前不一样的地方就是nickName="小Ai",在形参声明时给nickName赋值了,所以你在调用时如果不给它再初始化,就会是默认值,如果再初始化就会将初始化的值赋给nickName,覆盖了原来的值,但并不是所有的值都可以作为"可选参数",既然可给可不给,那要是你不给形参了,要是编译器不能知道形参的值,岂不是会报错啊,所以可做可选参数的是,对于值类型只能是编译器编译时明确知道它的默认值的,对于引用类型必须是默认值为null的