• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jk-2048
博客园    首页    新随笔    联系   管理    订阅  订阅
刘铁猛C#学习笔记12 参数种类详解

一、值参数(传值参数、值传递)

指参数的种类为值参数,而非参数数据类型为值类型

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:求集合内元素的平均值
(大概里面有很多关于集合的扩展方法)
 

总结

 
posted on 2024-02-23 23:07  JK降谷羽  阅读(105)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3