标签:输出 12 C# 刘铁猛 参数 引用 params 实参 方法
一、值参数(传值参数、值传递)
指
参数的种类为值参数,而非参数
数据类型为值类型
1.值类型的传值参数
类似一个新声明的局部变量,或传进来的
实参的一个
副本
可以在方法体内重现赋值,但其在方法体内被赋值时,
不会影响传进来的
本体
2.引用类型的传值参数
引用类型变量存储的是实例在堆内存中的地址
(1)在方法中给形参赋了新值
引用变量作为
实参传进方法后会产生一个副本(
形参),形参里存的也是实参指向的对象的地址
也就是说,一开始,
引用形参和
引用实参,指向的是
同一个实例对象
但如果在
方法体内对形参进行了
赋值,
形参指向的会是赋给他的
新对象的地址
但不会对
方法外的
实参产生任何影响,实参仍然指向
原对象地址
(实际编程中,这种操作是非常少见的)
(2)不赋新值,只操作对象
由于形参和实参指向的都是存在堆内存中的
同一个对象!!!!!!!
所以对象内的成员值会被改变
所以在方法内使用值参数,当参数为引用类型时,也可能导致方法外的东西发生改变!
打破了值参不会影响方法外事物的神话
这种使用在实际开发中比较少见
一般将这种方法修改了参数引用对象的值的操作,称作某个方法的
副作用(side-effect)
一般来说方法还是通过
返回值来发挥
主作用,副作用的情况要尽量避免
二、引用参数ref(引用传递)
指
参数的种类为引用参数,而非参数
数据类型为引用类型
引用参数不会为传进来的实参创建副本
也就是说,引用参数
直接指向实际参数的变量存储位置
关键:形参与实参完全统一为一体,参数在方法内与方法外完全一致,患难与共
形实统一,内外统一
作为调用方法时用引用传递传进来的变量,在此之前一定要有实际的赋值
且调用时在引用参数前必须加上
ref关键字
1.值类型的引用参数
参数并非传进来的参数的副本,而是
存在内存中同一个地址的同一个值
当引用传递的参数在方法内被赋了新值时,
方法外的变量也会随之一起改变
(与C、C++中的指针有关?)
带有引用参数的方法,是用
ref关键字,来
显式地强调在有意地
利用函数的副作用改变参数的值
在声明和调用时都要写上ref
2.引用类型的引用参数
在方法体内对引用类型的引用参数重新赋值时,方法内的形参指向了赋给他的新对象
由于对应引用传递,形参与实参是一体的,所以
方法外的实参变量,也跟着指向了这个新对象
如上实验结果表明,在方法内赋值后,方法外的变量一同指向了方法内创建的新对象
方法外实参与方法内形参,
哈希识别码的值完全一致,二者指向的是同一个实例对象,且在方法内被赋值时会一同改变
若使用引用类型引用参数,但不为参数赋新值,只操作实例对象的成员
这样使用的效果和引用类型值参数是完全一样的,只是内存机理不一样
实验结果发现,不对引用类型的参数赋新值,只操作字段
哈希识别码没有改变,方法内外参数指向的实例对象都没有改变,只有实例对象的成员字段被改变了
效果上与值传递的引用变量一样,但内存机理不同
值传递创建了实际参数的副本,引用传递没有创建副本
但值传递参数的本体和副本,存储的都是同一个实例在堆内存中的地址,相当于两个变量存一个地址
引用参数没有创建副本,是一个变量存一个地址
三、输出参数out(输出形参)
方法作为数据的加工厂,产物只有一个返回值
那么如果希望一个方法有
多个产物,就要用输出参数
也是一种对方法副作用的利用,利用输出参数,获得除返回值之外的额外输出
输出参数和引用参数一样,
不为参数创建副本
引用参数在传进方法之前要先赋值
输出参数在传进方法之前不用赋值
1.值类型的输出参数
与引用传递类似由于输出参数不创建副本,所以给参数赋值,方法体外的变量也会同时获得新值
C#已有示例:
规则:
1.输出参数在方法体里必须被赋值
2.输出参数名需要是一个已声明的变量?
3.在有输出参数的方法中,如果方法执行失败,作为输出参数传进来的变量原本的值可能会被覆盖而丢失。所以作为输出参数的已有变量,一般不需要赋初始值
2.引用类型的输出参数
与引用传递类似,方法内的参数被赋新值,指向一个新对象后,方法外作为输出参数的变量也会一同被改变,指向新对象
使用例子:方法带有尝试性质,不确定是否真的能执行
就可以用返回值装一个bool变量,用来判断是否能够执行
用输出参数out来装方法的一个或多个输出值
用来尝试性的将信息灌装进实例对象中
四、params特殊数组参数
必须是形参列表的
最后一个,用
params修饰
示例:数组求和函数
1.不使用params的情况
不使用params修饰符的情况下,也可以用数组名当作函数的参数
声明时不用修饰,只需要把形参类型写为带索引器[ ]的
调用:调用时参数直接写数组名,不用加索引器[ ]
2.使用params的情况
声明功能声明时使用了params修饰符,与不使用没有什么区别
但是调用方法时多了一个选择,可以不提前声明一个数组来作为参数,可以直接把想作为参数的数组的
元素直接列在
方法的参数列表()中,编译时会自动创建一个object类型的数组,将元素放进去作为参数传入方法
当参数类型为params数组参数时,
调用时就可以输入任意个数的参数!!!!!
非常方便
C#已有示例:天天用的打印方法
当参数类型为params数组参数时,
调用时可以输入任意个数的参数
所以打印方法可以一次打印任意个数的字符串
C#已有示例2:字符串分割方法
str.Split方法的参数是一个
params字符串数组,参数列表中,依次写上了各个
分隔符,可以写任意个数的参数,返回值也是一个字符串数组,在按顺序用
分隔符切割后,方法返回切割好的各个字符串
重要注意事项
由于params数组参数调用时可写无限个参数的特性
一个方法只能有一个params数组参数!
params数组参数必须是方法的参数列表中的最后一个!
五、具名参数
是一种调用方法时的参数使用方法
参数带有名字,参数的位置不再受约束
先正常声明一个方法
调用时写上参数的名字+冒号:,参数的位置就可以不再受参数列表顺序的约束
而且这样写上参数名字的调用方法,可以
六、可选参数
声明时参数具有
声明时给参数加上
在调用时就会显示参数是可选的
不写参数就会按声明时写的默认值去执行
编程规范:不推荐使用可选参数(不如用重载?)
七、扩展方法(this参数)
用于给一个已有的、不方便修改源码的类型,添加追加方法
扩展方法必须是public static的,
编程规范:并且必须放在一个静态类(名字一般为SomeTypeExtension)中
由this修饰的参数必须是参数列表中的第一个
C#的很多强大的功能都是基于扩展方法,包括
这里涉及委托和拉姆达表达式,以后再详细学习
All方法并不在List的定义中,这是一个扩展方法,写在Linq命名空间旗下的Enumerable类中
Linq命名空间中包括:
包括
All:查询集合中是否所有元素都满足(倒A标志)
Any:查询集合汇总是否有至少一个元素满足(反E存在标志)
Average:求集合内元素的平均值
(大概里面有很多关于集合的扩展方法)
总结
标签:输出,
12,
C#,
刘铁猛,
参数,
引用,
params,
实参,
方法
From: https://www.cnblogs.com/jk-2048/p/18030534