可能更有效率的学习方式是先系统泛读,再在实战中根据需要翻书。我讨厌在语法中裹足不前的状态,这次再快进一波。
1. 三个参数修饰符 ref out params
ref表示按引用传参,out加了一道必须返回值的验证,params可用于传多个参数非常方便。
2.属性
相较于C++常需自己写读写方法,C#算是先进一步,自动实现的属性已经大大简化写法,要习惯用。
3.const readonly
const在C++中经常被考不多说了。
readonly我一度质疑过它存在的意义,后来想通了,相比只读的属性,readonly特点是成员在类内部也无法被改变;相比const,readonly特点是可以在构造函数内赋值。
4.扩展方法
不知道此概念前,也自发产生过类似的需求,Unity的很多类缺一些好用的方法,但又不开源,自然会想到如何对其进行扩充。
了解了实现方式后,个人觉得还是不要用这编辑器抖机灵的玩意了。代码的稳定性永远重于可维护性。
5.继承
用virtual override重写的方法,实例默认调用最远的实现。用virtual new,则调用new之前的。
sealed除了可以密封整个类,还可以单独密封方法。
abstract类类似一个方法全是纯虚函数的C++类。
6.is as
is类型判断 as类型转换
7.接口
虽然网上没怎么看到类似的说法,虽然自己C++用得其实跟屎一样,我还是要说,这可能是C#比C++先进的又一点,完爆多继承,虽然我没怎么用过多继承。
8.装箱、垃圾回收
值类型间引用类型互转时会发生装箱拆箱,频繁的话会影响性能。这一点我先随便说说,真实的体会实战中再注意看吧。
自动垃圾回收发生时机虽然随机,但C#还是提供了一些控制方法的。
9.异常处理
我现在做读表值解析时必加try catch,其他体验不深。
10.泛型
用得多,写得少,要写时再看吧。
11.委托
说就是函数指针也没人会打我。
C#一代代更新,很多工作都只是在简化语法增强可读性,Lambda表达式真是装逼利器,当初看到时一脸懵逼,现在我也会用啦。
顺便说下我们的框架中自己写了一套通用的委托Action和Func,假如没搞错的话是发生在Mono不支持C#3.0时代的事了,具体有多久远我不知。
事件以后做游戏肯定逃不开的,到时候再细说。
12.LINQ
《深入理解C#》第三版15页——“事实上,许多人初识LINQ时(但在仔细研究它之前),第一个反应就是抗拒,因为它似乎纯粹就是将SQL引入了语言,目的是为了加强与数据库交互的能力”,对此我深有同感,虽然我没玩过数据库SQL也不咋地。
这玩意也是你不知道也能活得很好,知道能活得更爽那种,所以等我需要做大量集合操作时,再研究它吧。
13.反射
可能和Editor这块关联较大,目前以我的姿势水平,确实就是觉得没什么卵用。
不得不吐槽下装逼的人实在是太多了,我见过有个人问“反射存在的独特意义”之类的问题,然后下面一堆说“等你再过几年就知道了”之类的答案,显得自己经验有多丰富,但就是他妈不说点有用的。
14.多线程
由于我开发的项目和维护的这套框架的特殊性,个人对多线程这个东西是有阴影的,甚至于影响到了我对它的看法。我大致说下:
原框架采取了双线程的架构思路,将“渲染”及“逻辑”两块分在了两个线程中。
然而Unity引擎是帮我们封装了渲染工作的,所以框架所谓的“渲染”,实际也只是一些CharacterController.Move()之类的代码。同时需要注意一点,Unity的组件是无法在分线程中使用的,所以与其说是“渲染”和“逻辑”线程,不如干脆说是“无法分到分线程的逻辑”和“可分到分线程的逻辑”线程。于是,在两个线程间传递信息让一切原本可以很简单的工作变成了一场灾难。
在痛苦地将所有可以三步调用解决的问题以各种委托、层层传参十步调用方式解决后,我们惊讶地发现,“逻辑”线程的执行时间不到“渲染”线程的千分之一。最后就把两个线程合并了,发现并没有任何问题,性能显然也没有丝毫影响。
一开始我对框架的这种疯狂到处乱调的方式是膜拜的,以为是多么高端的设计模式,后来幸得主程点拨,才识破了它的跳大神。大道至简,大巧不工啊。
对此,我只能无责任给出一种猜测,原框架是用于那种“千人万人同屏”的端游页游服务端,渲染工作相对简单以至于用时与逻辑部分相当了,这时采取这种多线程架构也许能将性能翻倍,比如原本支持2000人的服务器现在可以支持4000。
但我从一个U3D游戏客户端程序的角度出发,还是认为,两倍三倍的性能优化并不算是什么真正意义的优化,游戏遇到的性能问题往往是一个十倍百倍的问题,那么这种时候明显和有没有用多线程没半毛钱关系了。
搞懂协程意义更大,可能网络和日志之类的确实要开新线程吧。
15.public、 internal、protected、private、 protected internal
最后补个基础的,可访问性修饰符一共有五个,默认是internal(程序集内public,假如没搞错的话)。
protected internal实际上是protected和internal的并集。