《随笔十八》——C#中的 “ 【《Effective C#》提炼总结】提高Unity中C#代码质量的22条准则 ”

目录

引言

本文内容思维导图式总结

原则1:尽可能地使用属性,而不是可直接访问的数据成员

原则2:偏向于使用运行时常量而不是编译时常量

原则3: 推荐使用is 或as操作符而不是强制类型转换

原则4: 推荐使用条件属性而不是#if条件编译

原则5:理解几个等同性判断之间的关系

原则6:了解GetHashCode( )的一些坑

原则7:理解短小方法的优势

原则8:选择变量初始化而不是赋值语句

原则9:正确地初始化静态成员变量

        原则10:使用构造函数链(减少重复的初始化逻辑)

原则11:实现标准的销毁模式

原则12:区分值类型和引用类型

原则13:保证0为值类型的有效状态

原则14:保证值类型的常量性和原子性

原则15:限制类型的可见性

原则16:通过定义并实现接口替代继承

原则17:理解接口方法和虚方法的区别

原则18:用委托实现回调

原则19:用事件模式实现通知

原则21:仅用new修饰符处理基类更新

原则22:尽量减少在公有API中使用动态对象



引言



我们知道,在C++领域,作为进阶阅读材料,必看的书是《Effective C++》。 而《Effective C#》之于C# ,是类似《Effective C++》之于C++一样的存在。

这篇文章,将《Effective C# Second Edition》一书中适用于Unity游戏引擎里使用C#的经验之谈进行了提炼,总结成为22条准则,供各位快速地掌握这本书的知识梗概,在Unity中写出更高质量的C#代码。

需要这本书的朋友可以点此链接下载: 链接:https://pan.baidu.com/s/1zoKp9MqA7VVZiyEBgsBVIg   提取码:8efj 
 


 

《Effective C# Second Edition》一书原本有50条原则,但这50条原则是针对C#语言本身以及.Net来写的,我在阅读过程中,发现是有些原则并不适用于Unity中mono版本的C#的使用。于是,在进行读书笔记总结的时候,将不适用的原则略去,同时将适用的原则进行提炼,总结出22(后来发现第22条也是.NET的特性,Unity版本的mono并没有实现,所以严格意义上来说是21条)条,构成本文的内容。

需要注意,因为是挑出了书中适用的准则,导致准则序号有些跳跃,为了阅读方便,本文对这些序号进行了重新排列。重排后,标题中与书中序号不一样的准则,都在该原则总结的末尾注明了对应的原书序号。

同样地,作为总结式文章,所以每一条的内容都高度概括,也许理解坡度比较陡,若有读到不太理解的地方,建议大家去阅读原书,英文版和中文版均可,看看原书中提供的各种代码与示例,这样掌握起来就会事半功倍。

 


本文内容思维导图式总结


以下是本文内容,提高Unity中C#代码质量的22条准则的总结式思维导图:


原则1:尽可能地使用属性,而不是可直接访问的数据成员


属性(property)一直是C#语言中比较有特点的存在。属性允许将数据成员作为共有接口的一部分暴露出去,同时仍旧提供面向对象环境下所需的封装。属性这个语言元素可以让你像访问数据成员一样使用,但其底层依旧是使用方法实现的。使用属性,可以非常轻松的在get和set代码段中加入检查机制。


需要注意,正因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性:


1)属性增加多线程的支持是非常方便的。你可以加强 get 和 set 访问器(accessors)的实现来提供数据访问的同步。

2)属性可以被定义为virtual。

3)可以把属性扩展为abstract。

4)可以使用泛型版本的属性类型。

5)属性也可以定义为接口。

6)因为实现属性访问的方法get与set是独立的两个方法,在C# 2.0之后,你可以给它们定义不同的访问权限,来更好的控制类成员的可见性。

7)为了和多维数组保持一致,我们可以创建多维索引器,在不同的维度上使用相同或不同类型。

无论何时,需要在类型的公有或保护接口中暴露数据,都应该使用属性。如果可以也应该使用索引器来暴露序列或字典。现在多投入一点时间使用属性,换来的是今后维护时的更加游刃有余。
 


原则2:偏向于使用运行时常量而不是编译时常量


对于常量,C#里有两个不同的版本:运行时常量(readonly)和编译时常量(const)。

应该尽量使用运行时常量,而不是编译器常量。虽然编译器常量略快,但并没有运行时常量那么灵活。应仅仅在那些性能异常敏感,且常量的值在各个版本之间绝对不会变化时,再使用编译时常量。

 

编译时常量与运行时常量不同之处表现在于他们的访问方式不同,因为Readonly值是运行时解析的:

  • 编译时常量(const)的值会被目标代码中的值直接取代。
  • 运行时常量(readonly)的值是在运行时进行求值。引用运行时生成的IL将引用到readonly变量,而不是变量的值。

这个差别就带来了如下规则:

编译时常量(const)仅能用于数值和字符串。

 

● 运行时常量(readonly)可以为任意类型。运行时常量必须在构造函数或初始化器中初始化,因为在构造函数执行后不能再被修改。你可以让某个readonly值为一个DataTime结构,而不能指定某个const为DataTIme。

 

● 可以用readonly值保存实例常量,为类的每个实例存放不同的值。而编译时常量就是静态的常量。

 

● 有时候你需要让某个值在编译时才确定,就最好是使用运行时常量(readonly)。

 

● 标记版本号的值就应该使用运行时常量,因为它的值会随着每个不同版本的发布而改变。

 

const优于readonly的地方仅仅是性能,使用已知的常量值要比访问readonly值略高一点,不过这其中的效率提升,可以说是微乎其微的。


综上,在编译器必须得到确定数值时,一定要使用const。例如特性(attribute)的参数和枚举的定义,还有那些在各个版本发布之间不会变化的值。除此之外的所有情况,都应尽量选择更加灵活的readonly常量。

 
 


原则3: 推荐使用is 或as操作符而不是强制类型转换


C#中,is和as操作符的用法概括如下:

  • is : 检查一个对象是否兼容于其他指定的类型,并返回一个Bool值,永远不会抛出异常。
  • as:作用与强制类型转换是一样,但是永远不会抛出异常,即如果转换不成功,会返回null。


● 尽可能的使用as操作符,因为相对于强制类型转换来说,as更加安全,也更加高效。


● as在转换失败时会返回null,在转换对象是null时也会返回null&

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值