《Effective C#》快速笔记 - C# 高效编程要点补充

目录

  • 四十五、尽量减少装箱拆箱

  • 四十六、为应用程序创建专门的异常类

  • 四十七、使用强异常安全保证

  • 四十八、尽量使用安全的代码

  • 四十九、实现与 CLS 兼容的程序集

  • 五十、实现小尺寸、高内聚的程序集

  这是该系列的最后一篇。也许有些理论有可能会过时,我想它仍有存在的必要,人的知识水平也是一个不断成长的过程,学会站在前人的肩膀上,尝试不断的借鉴与总结。

四十五、尽量减少装箱拆箱

  1. 值类型是数据的容器,不支持多态。

  2. 装箱把一个值类型放在一个未确定类型的引用对象中,让该值作为引用类型所使用。拆箱指从引用类型的位置取出值的一个副本。

  3. 装箱和拆箱会在无意中创建许多副本,导致许多难以发现的 Bug。

  4. 使用接口而不是使用类型可以避免装箱,即将值类型从接口实现,然后通过接口调用成员。

  5. 装箱拆箱都是比较影响性能的手段,应该尽可能的避免装拆箱操作。

  6. 泛型可以避免装拆箱操作。

  7. 值类型装箱是隐式的,难以发现,需要自己多加注意。

  这里是一篇较为详细的关于装拆箱的博文:《装箱与拆箱》

四十六、为应用程序创建专门的异常类

  1.只有当用户会以不同的形式去处理错误时,才应该创建不同的异常类。

  2.自定义的异常类应该以“Exception”结尾,并且继承 System.Exception 或其他异常类。不过你也需要适当地包含该基类中的构造函数,内容直接交给基类实现即可。

    /// <summary>
/// 自定义的异常类
/// </summary>
public class MyException : Exception
{
public MyException() : base()
{ } public MyException(string s) : base(s)
{ } public MyException(string s, Exception e) : base(s, e)
{ } protected MyException(SerializationInfo info, StreamingContext cxt) : base(info, cxt)
{ }
}

  3.在抛出自定义的异常时,应该将原始的异常存放在 InnerException 属性中,这样就可以显示足够友好,并且信息丰富的异常:

        public void Do()
{
try
{
//DoException();
}
catch (DoException e)
{
var msg = $"该问题是博主故意引起的";
throw new MyException(msg, e);
}
}

  4.只有在存在不同类型的恢复操作时,才应该抛出不同类型的异常,定义异常类时,还要提供基类中支持的所有构造函数。此外,不要忘记使用 InnerException 属性来保存低层次的异常信息。

四十七、使用强异常安全保证

  1.Dave Abrahams 定义了 3 种安全异常来保证程序:基础保证、强保证,以及无抛出保证。

  2.强异常保证:从异常中恢复和简化异常处理之间提供了一个平衡点,如果一个操作因为某个异常中断,程序将维持原状态不变,操作要么彻底完成,要么就不会修改程序的任何状态。强异常保证的好处:任何时候若是捕获了异常,所有将要尝试的正常操作都不继续进行。程序当前的状态如尚未开始进行该操作一样。

  3.对将要修改的数据做防御性的复制,对这些数据的防御性复制进行修改,这中间的操作可能会引发异常,在出现异常时可将临时副本和原对象进行交换。

  4.终结器、Dispose() 方法和委托对象所绑定的目标方法在任何情况下都应当确保他们不会抛出异常。

四十八、尽量使用安全的代码

  1. .NET 运行时可以保证一些怀有恶意的代码不能直接渗透到远程计算机上执行。

  2. CLR 中的带有代码的访问安全设置,如:CLR 强制要求基于角色的安全认证,这样才能判断某些代码能否在基于一个特定的角色账号下运行。

  3. CLR 可以检查 IL 代码,确保它不存在潜在的危险行为。如:直接访问原始内存。

  4. 如果代码不需要任何的安全权限,就不需要使用 CAS 的 API 来判断访问权限,因为这样只会影响性能,额外增加 CLR 的工作量。

  5. 你可以使用 CAS 的 API 来访问一些受保护的资源,一般需要额外的权限。如非托管的内存和文件系统、注册表等。

  6. 一般来说,我们编写的 C# 代码都是安全的,除非你使用了 /unsafe。

  7. 应该尽可能地避免访问非托管内存。确实有需要的话,应该将其隔离在独立的程序集中。

四十九、实现与 CLS 兼容的程序集

  1..NET 运行环境与语言无关,我们创建的程序集必须与 CLS 保持兼容,这样才能保证其他的开发人员可以用另一种语言来调用你的组件。

五十、实现小尺寸、高内聚的程序集

  1. 如果我们都将所有的代码放在一个程序集中,这不利于组件的重用,也不利于系统的局部更新,若是可以将其拆分成小程序集,以组件的形式进行重用,就可以从一定程度上简化后续的开发工作。

  2. 我们用类进行功能的封装和数据的存储,只有公有的类、结构和接口才应该称为契约,被其它用户(或程序集)进行访问。

  3. 建议将程序拆分成多个程序集,把相关的类型放在同一个程序集中。

  4. 一个程序集应该是一个包含相关功能的,具有良好组织的一个库。如果不知道怎样的颗粒度最好,可以略微向小而多的方向倾斜。

  5. 如果所有参数和返回值都是接口,那么任何一个程序集都可以很容易地用另一个实现了相同接口的程序集进行代替。

  6. 更小的程序集同样可以降低程序启动时的开销。更大的程序集要花上更多的 CPU 时间来加载,且需要更多的时间来将必须的 IL 编译成机器指令。虽然只有启动时将被调用的代码会被 JIT 编译,但程序集是整体载入的。

  7. 在跨越程序集时,安全性检查会成为一个额外的开销。程序跨越程序集的次数越小,其执行效率越高。

  8. 性能的损耗对我们来说可以忽略不计,因为在开发时,我们着重的是代码的灵活度,所以不需要担心将大程序集拆分成小程序集的性能问题。

  9. 常见的程序集:小且仅专注于某个特定功能的程序集,大一些但包含通用功能的程序集。无论何种情况,都应该保证其尽可能合理的小,但不应该过度。

本系列

  《Effective C#》快速笔记(一)- C# 语言习惯

  《Effective C#》快速笔记(二)- .NET 资源托管

  《Effective C#》快速笔记(三)- 使用 C# 表达设计

  《Effective C#》快速笔记(四) - 使用框架

  《Effective C#》快速笔记(五) - C# 中的动态编程

  《Effective C#》快速笔记(六) - C# 高效编程要点补充


【博主】反骨仔

【原文】http://www.cnblogs.com/liqingwen/p/6827546.html

【参考】《Effective C#》

[.NET] 《Effective C#》快速笔记 - C# 高效编程要点补充的更多相关文章

  1. 《Effective C#》快速笔记(六)- - C# 高效编程要点补充

    目录 四十五.尽量减少装箱拆箱 四十六.为应用程序创建专门的异常类 四十七.使用强异常安全保证 四十八.尽量使用安全的代码 四十九.实现与 CLS 兼容的程序集 五十.实现小尺寸.高内聚的程序集 这是 ...

  2. C# Note22: 《Effective C#》笔记

    参考:<Effective C#>快速笔记(一)- C# 语言习惯 参考:<Effective C#>快速笔记(二)- .NET 资源托管 参考:<Effective C ...

  3. [.NET] 《Effective C#》快速笔记 - C# 中的动态编程

    <Effective C#>快速笔记 - C# 中的动态编程 静态类型和动态类型各有所长,静态类型能够让编译器帮你找出更多的错误,因为编译器能够在编译时进行大部分的检查工作.C# 是一种静 ...

  4. 《Effective C#》快速笔记(五)- - C# 中的动态编程

    静态类型和动态类型各有所长,静态类型能够让编译器帮你找出更多的错误,因为编译器能够在编译时进行大部分的检查工作.C# 是一种静态类型的语言,不过它加入了动态类型的语言特性,可以更高效地解决问题. 一. ...

  5. [.NET] 《Effective C#》快速笔记(四)- 使用框架

    <Effective C#>快速笔记(四)- 使用框架 .NET 是一个类库,你了解的越多,自己需要编写的代码就越少. 目录 三十.使用重写而不是事件处理函数 三十一.使用 ICompar ...

  6. [.NET] 《Effective C#》快速笔记(二)- .NET 资源托管

    <Effective C#>快速笔记(二)- .NET 资源托管 简介 续 <Effective C#>读书笔记(一)- C# 语言习惯. .NET 中,GC 会帮助我们管理内 ...

  7. [.NET] 《Effective C#》快速笔记(一)- C# 语言习惯

    <Effective C#>快速笔记(一)- C# 语言习惯 目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 ...

  8. 《Effective C#》快速笔记(一)- C# 语言习惯

    目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Conditional ...

  9. 《Effective C#》快速笔记(四)- 使用框架

    .NET 是一个类库,你了解的越多,自己需要编写的代码就越少. 目录 三十.使用重写而不是事件处理函数 三十一.使用 IComparable<T> 和 IComparer<T> ...

随机推荐

  1. 转换器5:参考Python源码,实现Php代码转Ast并直接运行

    前两个周末写了<手写PHP转Python编译器>的词法,语法分析部分,上个周末卡文了. 访问器部分写了两次都不满意,没办法,只好停下来,参考一下Python的实现.我实现的部分正好和Pyt ...

  2. js中关于string的一些常用的方法

    最近总结了一些关于string中的常用方法, 其中大部分的方法来自于<JavaScript框架设计>这本书, 如果有更好的方法,或者有关于string的别的常用的方法,希望大家不吝赐教. ...

  3. C++—动态内存管理之深入探究new和delete

    C++中程序存储空间除栈空间和静态区外,每个程序还拥有一个内存池,这部分内存被称为自由空间(free store)或堆(heap).程序用堆来存储动态分配的对象,即,那些程序运行时分配的对象.动态对象 ...

  4. TCP的三次握手(建立连接)与 四次挥手(关闭连接)

    一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: TCP报文格式上图中有几个字段需要重点介绍下: (1)序号:Seq序号,占32位 ...

  5. CentOS6.5下安装oracle11gR2

    安装前须知 内存(RAM)的最小要求是 1GB,建议 2GB 及以上. 虚拟内存 swap 建议:内存为 1GB~2GB 时建议swap大小为内存大小的 1.5 倍:内存为 2GB~16GB 时建议s ...

  6. 老司机实战Windows Server Docker:5 Windows Server Dockerfile葵花宝典

    前面两篇(简单运维1.简单运维2)介绍了一些Windows Server Docker相关的基本运维知识.今天这一篇,Windows Server Dockerfile葵花宝典,涵盖了许多典型场景的W ...

  7. PRINCE2有用吗?

    PRINCE2项目认证--在欧美国际久负盛名,在国内近来才逐渐为业内人士所了解.PRINCE2认证2007年首入中国,目前国内参加培训并获取认证的专业人士不足五万人,PRINCE2全称为"受 ...

  8. Android实战(一)学习了多个控件实现登录及记住密码功能

    首先确定一下需要的控件: 两个EditText:用于输入账号和密码 一个button:用于登录查看账号和密码是否正确 一个checkbox:用于记住密码和账户 一个Androidstudio:用于编写 ...

  9. 大数据测试之hadoop系统生态

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标,也是国内最早探索大数据测试培训的机构,开发了独有的课程体系.如果对课程感兴趣,请大 ...

  10. LoonAndroid自动检测输入框 --- Author: rose && lvyerose@163.com

    LoonAndroid框架,同时给我们提供了一套自动检测输入规则的工具,用起来很是方便,下面介绍一下这个东东的使用方法(注意,该说明是基于项目已经集成了LoonAndroid框架而言,如果您未集成该框 ...