编写高质量代码:改善C#程序的157个建议

编写高质量代码:改善C#程序的157个建议

2014-12-13 张子阳 推荐: 4 难度: 3

这本书汇集了C#编写中的一些建议、注意事项和小技巧,为了温故知新,又拿出来翻看了一遍。很多主题要阐述的内容是显而易见、不言自明的,就没有再写摘要。部分主题的名称起得并不够好,我进行了改动;个别建议是有争议的,我修改为了我认为合理的方式(红色字体)。

基本语言要素

  1. 正确操作字符串 注意隐式的装箱和拆箱,string str = "a" + 1.ToString(); 优于 string str = "a" + 1;。 拼装多个字符串时,使用 StringBuilder。
  2. 类型转换的方法
    1. 类型转换运算符(operator重载),例如 float j=0; int i = (int)j;
    2. 类型的静态方法,例如 TryParse()、Parse();实例方法,ToString()、ToDatetime()
    3. 使用帮助类,System.Convert,System.BitConvert
    4. 基类和子类之间的转换。
  3. 区别 as 与 is 能使用as的情况下使用as,性能会优于is。 as只能用于引用类型,is则都可以。
  4. 总是使用TryParse,不使用Parse
  5. 恰当使用Nullable<T>类型 如果数据库的字段可为null,那么对应的C#实体类属性也应当可以为null。使用int?而不是int。
  6. 区别使用readonly和const const是编译时常量,readonly是运行时常量;const只能加在基元类型上,且默认为static,readonly则无此限制。
  7. 将0作为枚举项的默认值
  8. 枚举要么全部显式赋值,要么全部不要赋值 个人建议全部显式赋值,因为很多时候是将枚举项的值存在数据库当中,如果不显示赋值,那么当在枚举项中间插入一个值的时候,后面的值会全部改变。因为枚举值默认是+1累进的。
  9. 为类型添加运算符重载
  10. 可以考虑为类型实现IComparable或者IComparer比较器接口
  11. 区别==和Equals() 默认情况下,它们是一样的;但通常重载Equals()表示“值相等”,==来表示引用相等。
  12. 重写Equals()时同时重写GetHashCode() 否则会出现潜在的不易察觉的BUG,例如在Dictionary<Key, Value>中,CLR内部查找的实际是Key值的HashCode。
  13. 类型格式化字符串 IFormattable和IFormatProvider的用法。这个两个接口项目中不常使用,但是IFormatProvider倒是可以作为分离变化的教程来学习。
  14. 深度复制和浅度复制
  15. 使用dynamic简化反射的实现 效率可以提高很多。

集合和LINQ

  1. 元素数量固定使用数组;不固定使用List<T>。 很多算法针对数组有优化。
  2. 遍历时尽可能使用foreach 1. 语法简化; 2.如果实现了IDispose,则会自动调用。
  3. foreach不能代替for
    1. foreach遍历时不可以对集合进行修改。
    2. foreach使用迭代器进行遍历,for使用索引器。
  4. 使用集合初始化器对集合进行初始化 数组:string[] list = { "1", "2", "3" }; 列表:List<Item> list = new List<Item>() { new Item(), new Item(), new Item() };
  5. 使用泛型集合,不再使用ArrayList
  6. 选择合适的集合 常用集合:数组、List<T>、Stack<T>、Queue<T>、Dictionary<TKey, TValue>、LinkedList<T>、HashSet<T>。
  7. 确保集合的线程安全 当T1对集合读,T2对集合写时,则可能出现潜在的BUG。
  8. 不要用List<T>作为自定义集合类的基类 因为List<T>没有virtual方法,无法重写,因此最好自己实现一个集合类的基类。
  9. 迭代器应当是只读的
  10. 注意集合类型成员的可访问性 如果集合类型的属性是可写的,则可能引发线程安全的问题(建议22)。因此最好这样设置:public List<Item> ItemList { get; private set; },只允许类型内部成员对集合属性进行赋值。
  11. 使用匿名类型存储LINQ查询结果
  12. 在查询中使用Lambda表达式 实际上我只用Lambda表达式,因为个人认为LINQ的查询语法相当怪异,像SQL又有不同,看上去很别扭。
  13. 理解延迟求值和主动求值的区别 LINQ查询表达式并没有立即执行,只有在执行ToList()或者遍历时才会执行。
  14. 区别LINQ中的IEnumerable<T>和IQuerable<T> 简单来说,IEnumerable<T>针对的是LINQ to Objects,IQuerable<T>针对的是LINQ to SQL。
  15. 使用LINQ,不需要再使用集合的比较器和迭代器 LINQ极大简化了集合操作,理解比较器和迭代器的原理还是重要的,但开发中已经不再需要去实现它们了。
  16. 在LINQ查询中避免不必要的迭代 使用First()、Take()等方法,比使用Where()迭代的次数更少。

感谢阅读,希望这篇文章能给你带来帮助!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

30 分钟 Java Lambda 入门教程

Lambda作为函数式编程中的基础部分,在其他编程语言(例如:Scala)中早就广为使用,但在Java领域中发展较慢,直到java8,才开始支持Lambda。

28540
来自专栏全栈架构

抱歉!不要用Java的语法思维来写Kotlin

如果你是像我一样是一名 优秀的Java开发者 ^_^,而且已经想用kotlin来实现你的程序,那么,抱歉!不要用Java的语法思维来写Kotlin,不要让kot...

15540
来自专栏技术博客

编写高质量代码改善C#程序的157个建议[动态数组、循环遍历、对象集合初始化]

    软件开发过程中,不可避免会用到集合,C#中的集合表现为数组和若干集合类。不管是数组还是集合类,它们都有各自的优缺点。如何使用好集合是我们在开发过程中必须...

16840
来自专栏TechBox

为什么不能在init和dealloc函数中使用accessor方法前言为什么不能在init中调用accessor为什么不能在dealloc中调用accessor结尾

17030
来自专栏小樱的经验随笔

【Java学习笔记之三十一】详解Java8 lambda表达式

Java 8 发布日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动。特性之一便是随同发布的lambda表达式,它将允许...

42450
来自专栏钟绍威的专栏

Properties+重温Map+本地计数器Map方法Properties的方法用Properties的好处

昨天想写一个记账本,发现并不能把项目名称与内容关联起来,于是乎我想到了map,可是又不知道map储存到文件中又怎么读出来,幸好今天遇到了properties ...

22170
来自专栏维C果糖

Guava 指南 之「使用和避免 null」

使用和避免null “null,糟糕透啦!” —— Doug Lea. “我称null为百亿美金的错误!” —— C. A. R. Hoare. 轻...

22270
来自专栏用户2442861的专栏

python中的多态

允许父类指针或名称来引用子类对象,或对象方法,而实际调用的方法为对象的类类型方法。

12510
来自专栏依乐祝

[译]聊聊C#中的泛型的使用(新手勿入)

今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发现了一些问题,因...

12840
来自专栏老九学堂

干货| 期末临近快捷C语言复习

? 盼望着盼望着,寒假近了 当然期末考试也就近了 C 语言,晦涩难懂 对于很多同学来说又是初次接触… 期末考试怎么办 不要担心!老九又出新篇章啦 总结了排序...

42370

扫码关注云+社区

领取腾讯云代金券