《C#入门详解》刘老师 传值/输出/引用/数组/具名/可选参数/扩展方法
传值/输出/引用/数组/具名/可选参数/扩展方法
-
传值参数
声明时不带修饰符的形参时值形参,一个值形参对应于一个局部变量,只是它的初始值来自该方法调用所提供的相应实参。传值参数会为传进来的实例参数创建一个副本,图片里的Notice。
1.值类型
2.引用类型,创建新对象
引用类型的变量存储的值就是引用类型实例在堆内存的地址
赋值前:参数初始值也是存储的一个地址,和方法外部的变量存储的是同一个地址,所以方法内部的参数和方法外部的变量指向的是同一个对象
赋值后:如果在方法的内部为参数赋了新值,一般情况下为引用变量赋值为new 操作符的表达式
using system; namespace ParametersExample { class program { static void main(string[] args) { student stu = new student(){ name="tim"}; somemethod(stu); console.writeline(stu.name);//方法外部变量所引用的实例没有改变 } static void somemethod (student stu) { stu = new student(){name="tom"}; //参数存进来之后,somemethod这个方法又为参数赋了一个新值,这个新值是新对象在堆内存中的地址,而这个新对象的name属性是Tom,所以我们打印出来的就是Tom console.writeline(stu.name); } } class student { public string Name{get;set;} } }
3.引用类型,只操作对象,不创建新对象
using system; namespace ParametersExample { class program { static void main(string[] args) { student stu = new student(){ name="tim"}; updateobject(stu); console.writeline(stu.name); } static void updateobject (student stu) { stu.name = "tom"; console.writeline(stu.name); } } class student { public string Name{get;set;} } } /*通过参数,访问了由参数所引用的这个对象,并且修改了对象里的值,由于变量和参数指向的同一个对象。通过参数修改了对象的值,当再用变量访问这个对象的时候,拿到的也是更新之后的值*/
-
输出参数
用out修饰符声明的形参,输出形参不创建新的存储位置。相反,输出形参表示的存储位置恰是在该方法调用中作为实参给出的那个变量所表示的存储位置。
1.值类型
bool b = double.tryparse(arg1,out x);这个方法有一个返回值,是一个bool类型的,要用一个bool类型的变量来接收这个返回值。
2.引用类型
using system; namespace ParametersExample { class program { static void main(string[] args) { student stu = null; bool b = studentfactory.create("tom",28,out stu); if (b==true) { console.writeline("student{0},age is{1}",stu.name,stu.age);} } } class student { public string Name{get;set;} public int age{get;set;} } class studentfactory { public static bool create(string stuname ,int stuage ,out student result) { result = null; if(string.isnullorempty(stuname)) { return false;} if(stuage<20 || stuage>80) { return false;} result = new student(){name=stuname ,age =stuage}; return true; } } }
-
引用参数
引用形参是用ref修饰符声明的形参。不会为传进来的参数创建副本,引用参数直接指向传进来的实际参数所指向的内存地址。引用形参表示的存储位置恰是在方法调用中作为实参给出的那个变量所表示的存储位置。
1.值类型的变量
using system; namespace ParametersExample { class program { static void main(string[] args) { int y = 1; sideeffect(ref y); console.writeline(y); //y=101 } static void sideeffect (ref int x) { x=x+10; } } }
2.引用类型,创建新对象
方法体里为参数赋了新值,如果对一个引用类型的变量赋值,是一个new操作符表达式。由于参数和变量指向的是内存中同一个地址。虽然在方法体里是为参数赋值,实际上是方法之外的变量也指向了新创建的对象
using system; namespace ParametersExample { class program { static void main(string[] args) { student outterstu = new student(){ name="tim"}; console.writeline(outterstu.name); //tim console.writeline("======================"); sideeffect(ref outterstu); //tom console.writeline(outterstu.name); //tom } static void sideeffect (ref student stu) { stu = new student(){name="tom"}; console.writeline(stu.name); } } class student { public string Name{get;set;} } }
-
数组参数
-
具名参数
-
可选参数
-
扩展方法(this参数)
1.方法必须是公有、静态的,即被public static所修饰
2.必须是形参列表中的第一个,由this修饰
3.必须由一个静态类(一般类名为SomeTypeExtension)来统一收纳对sometype类型的扩展方法
4.例子:linq方法
using system; namespace ParametersExample { class program { static void main(string[] args) { double x =3.14159; double y =x.round(4); // round只接收一个参数,.x就是round方法的第一个参数 ,现在只需输入第二个参数 console.writeline(y); } } static class doubleExension { public static double round(this double input , int digits ) { double result = math.round(input, digits); return result; } } } /*当我们无法对一个类型的源码进行修改的时候,可以使用扩展方法为这个目标数据类型追加方法。*/
-
应用场景