类的成员

一、字段

1.概念

字段保存了一个值类型的实例或对一个引用类型的引用

2.修饰符

static
表示字段是类型状态的一部分,而不是对象状态的一部分
readonly
表示字段只能由构造器方法中的代码写入
.volatile
表示字段可以由多个同时执行的线程修改。它不受编译器优化的限制,读取这个变量的值时候每次都是从momery里面读取而不是从cache读,这样保证每次它取到的值都是最新的

二、属性

属性看起来和字段差不多,实际它是叫做“访问器”特殊方法,它本质上是方法,既然是方法,那么就它实际也就涉及参数

1.无参属性

字段如果定义成public,那么会存在安全隐患,因为字段代表一个类的基础状态,这样可以被外部随意访问,很容易产生安全漏洞,所以建议使用属性类封装字段

C#提供了语法糖,如果你不需要在属性里添加逻辑,可以写成这样

注意:

(1)属性不能作为out或ref参数传给方法

1.有参属性

C#中的有参属性叫做索引器,可以看成是对[]操作符的重载

当然,它既然本质上是方法,也可以定义多个参数

二、方法

1.构造

1)引用类型

概念
实例构造方法:初始化类型实例的方法,它永远不能被继承,类只有类自己定义的实例构造器,若是没有显式的声明构造函数,它自动创建一个默认的无参构造
创建实例时的执行顺序
(1)为实例的数据字段分配内存
(2)初始化对象的附加字段(类型对象指针和同步索引块)
(3)把为对象分配的内存归零
(3)调用实例构造,初始化对象

注意:

1)使用这种内联的方式初始化字段

它在幕后实际转换成了构造中的代码进行初始化,和在构造中初始化实际并无区别
2)不要在构造器中调用虚方法
派生类如果实现了父类的虚方法,那么父类构造调用了这虚方法,会导致这个时候它调用了子类虚方法的实现,但是这个时候,还没有完成对所有字段的初始化,会出现无法预测的问题
3)代码膨胀问题
代码膨胀(英语:Code bloat)是指代码有着不必要的长度、缓慢或者其他浪费资源的情况
以下代码就存在代码膨胀问题:

编译器生成代码时,在构造开始的位置,初始化字段,然后调用基类构造,最后执行构造器自己的代码,那么问题来了,现在我们有两个构造…
所以,我们可以预见,字段的初始化会执行两次,每个方法执行一次,这会多生成一份初始化字段的代码,这就是代码膨胀
为解决这个问题,需要创建一个公共的构造器,让另一个构造器显式调用它

2)值类型

值类型也可以定义构造函数

注意:

(1)值类型不允许定义无参构造
(2)值类型构造必须初始化全部字段,若是字段很多,但是只有一两个字段需要特别初始化,可以使用以下这种简便写法

这里要注意,赋值的字段一定要在this赋值的代码之后

3)类型构造器

C#除了实例构造还支持类型构造器

注意:

(1)类型构造不允许添加访问修饰符
(2)必须为static
(3)一个类型中只能定义一个,且必须无参
(4)它的调用由CLR负责,但是CLR只调用引用类型的静态构造

2.操作符重载

操作符的重载方法必须是public和static的,并且参数中至少有一个与定义这个方法的类型相同,下面以,+举个例子

3.转换操作符

将对象从一种类型转换成另外一种类型,必须是public和static的,参数和返回值至少有一个与定义方法的类型相同

4.扩展方法

当你觉得一个类的方法不前面时,你可以手动添加扩展方法,扩展方法的好处就是你可以不去修改源代码,添加自己的方法

注意:

(1)扩展方法必须在非泛型静态类中声明
(2)第一个参数为要扩展的类型,并用this标记,只有第一个参数能用this标记
(3)定义扩展方法的类,不能是嵌套类,它必须在顶级静态类中定义
(4)不要给object类型添加扩展方法,这样在所有的表达式类型上都能调用,存在很大的安全隐患
(5)可能会存在版本问题,例如,我给string添加了一个扩展方法“Auto”,若是C#未来给string同样添加了一个叫做“Auto”的方法,那么就会出现冲突

4.分部方法


关键字:partial
简单的理解,就是可以把一个类分成很多部分写,它们所有的方法及属性和写在一个类里没有区别
这样,实际可以提高代码的可读性,实现类内的逻辑分层
分部方法,就是可以在一个分部类里定制行为(就是方法),在另外一个分部类里实现,有点像子类实现父类的方法一样

注意:

(1)分部方法不允许添加访问修饰符,默认private
(2)分部方法必须有定义声明,即:

(3)分部方法的返回值只能是void
(4)分部方法的参数不能添加out修饰符,但是可以用ref

三、参数

1.可选参数

为参数提供默认值的方式,可以在调用方法时选择不提供部分参数

注意:

(1)默认值必须是常量值
(2)带有默认值的参数,必须声明在实参列表的尾部

2.命名参数

3.以传引用的方式传递参数

关键字:ref 和 out
可以让值类型的参数,以传引用的方式传递进来,ref和out实际会生成同样的IL代码,也就是说,CLR并不区分它们,用法上也至少稍有差别


正常情况就是上面这样,值类型只是传值进去,所以方法内部赋值的10不会改变value对象的值
ref:


使用ref后就相当于是传递引用的方式传递参数
out用法和ref相同
唯一的区别就是 ref传递的变量必须使用已经赋值的变量。out不需要
##4.可变数量的参数

我会在我的公众号上推送新的博文,也可以帮大家解答问题
微信公众号 Andy and Unity 搜索名称或扫描二维码
在这里插入图片描述
希望我们能共同成长,共同进步

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值