Effect C# 学习笔记 杂项(持续更新)

条目45 尽量减少装箱和拆箱

.NET Framework用装箱和拆箱在值类型和引用类型之间架起了桥梁。

装箱将把一个值类型放在一个未确定类型的引用对象中,让这个值类型也能在需要引用类型的地方使用,而拆箱则是指从箱中获取出其中值类型的副本。

装箱和拆箱都是较为影响性能的操作,有时还会创建对象的临时副本,进而导致一些难以发现的Bug。你应尽量地避免装箱和拆箱操作。

状态会把值类型转换为引用类型。这个新的引用类型(即箱子)将分配于堆上,该值类型的一个副本会存放在引用类型的内部。

箱子包含了值类型的副本,并提供了值类型公有接口的功能。若是需要从箱子中获取数据,那么将创建其中值类型的一个副本并返回。装箱和拆箱的关键之处:装箱时存放的是值类型的副本,获取箱中数据时返回的是值类型的另一个副本。

泛型能让你用泛型类或泛型方法来避免装箱/拆箱操作。

.NET Framework中很多方法的参数类型仍为System.Object,因此这些API还是需要拆行装箱和拆箱操作。这个过程是自动的,若是将值类型传递到需要引用类型的地方,那么编译器将自动生成装箱/拆箱的指令。此外通过接口指针使用值类型时,也会自动发生装箱/拆箱操作。

等价于:

在WriteLine中:

你应在将值类型传递给WriteLine之前,手工将其转换成字符串:

由此给出避免装箱的第一条规则:小心到System.Object的隐士转换。若可以避免的话,不要用值类型代替System.Object。

在使用集合类型时,尽量使用泛型集合。

值类型可以转换为System.Object或其他接口的引用。转换过程是隐式的,也就更难以发现。装箱和拆箱的操作会在你无意识中创建副本,这往往会导致Bug。以多态的形式处理值对象也会带来性能上的损失。小心那些将把值类型转换成System.Object或接口类型的代码。例如在集合中存放值类型、调用System.Object中的方法、转型为System.Object等。应该尽量避免这些操作。

条目46 为应用程序创建专门的异常类

异常是一种报告错误的机制,在这种机制中,错误的抛出位置和处理位置可能相距甚远。因此,有关错误的所有信息都必须包含在异常对象中。此外,还可能需要将低级别的错误转换成应用程序领域内特定的异常,同时保留原始错误的所有信息。

第一步是了解何时以及为何创建新的异常类,并考虑应该如何组织完备的异常层次结构。开发者使用你的类库编写catch子句时,会根据异常运行时类型的不同有区别地执行处理逻辑。

首先,异常并不适合于你所遇到的每一个问题,虽然没有什么明确的指导意见,但建议对于那些如若不及时报告并处理会引发长久问题的错误,应该抛出异常。

齐次,编写throw语句并不代表就要在此处创建一个全新的异常类。在将低层次的异常转换成更高级别的、包含更多上下文信息的异常。这种处理方式称为异常转换。

要再次强调的是,提供不同异常类的原因是,让捕获异常的代码能根据不同的错误条件给出不同的处理方式。查看哪些可能会进行同类型恢复操作的异常条件,然后按照这样的标准创建专门的异常类。

集合初始化时应指定初始值大小且需要向4对齐

以List为例。

这是因为集合类型的对象在触发扩容机制时,会生成一个更大空间的集合类型来存储(原始大小*2),且因为默认大小为4,所以在指定大小时向4对齐,保证指定的大小是4的倍数且向上取整到刚好放得下现有的集合内项的数目。这是因为如果不是4的倍数的时候,下一次再有类型去申请内存空间的时候,它无法保证能申请到自己想要的大小,就会导致大量的内存碎片化,比如剩下3个大小的空间没有对象能申请到。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值