C# 《编写高质量代码改善建议》整理&笔记 --(二)集合
题记:这篇,主要就是讲述集合之类。好好总结一番。
1.多数情况下使用foreach进行循环遍历
先假设一下如果对集合进行遍历,假设存在一个数组,其遍历模式可能采用依据索引来进行遍历的方法;又假设存在一个HashTable,其
遍历模式可能按照键值来进行遍历。无论是哪个集合,他们的遍历没有一个公共的接口,那么客户端在调用的时候,相当于对具体类型进行了
编码,这样一来,当需求发生变化时,就必须修改我们的代码。并且由于客户端代码过多的关注了集合内部的实现,代码的移值性就会变得很差,这直接违反了面向对象中的开闭原则,于是迭代器模式就诞生了。
(简而言之,就是在不管集合内部如何实现的情况下,完成遍历)
foreach 优势:语法简明,自动将代码置入try-finally,实现了IDispose接口,他会在循环结束后调用Dispose方法。
2.foreach 不能代替for
foreach不支持循环时对集合进行增删操作。如果在foreach中增/删某一元素,则会抛出异常。
原因:foreach循环使用了迭代器进行集合的遍历,它在FCL提供的迭代器内部维护了一个对集合版本的控制。
集合版本:简单来说就是一个整型变量,任何对集合的增删操作都会使版本号+1。
foreach循环会调用MoveNext方法来便利元素,MoveNext方法内部会进行版本号的检测,一旦版本号变动,
就会抛异常。
for循环在实现上所有不同。(使用索引器,不会对版本号判断)循环中增删元素不会抛异常。
由于for循环和foreach循环在实现上有所不同(前者是索引器,后者是迭代器),因此两者在性能上的争议
没有停止过。但是双方都承认在时间和内存上存在损耗。
3.选择正确的集合。

从图中可以看出集合总体分为线性集合和非线性集合。
线性集合:指元素具有唯一的前驱和后驱的数据结构类型;
非线性集合指具有多个前驱和后驱的数据结构类型。
(非线性集合用的比较少,而且还很难,这边就不讲述)
如果集合的数目固定并且不涉及转型,使用数组效率高,否则使用List<T>
线性集合按存储方式又分为直接存储和顺序存储。
直接存储
是指该类型的集合数据元素可以直接通过下标(index)来访问,如Array(List,数组),string,struct
优点:向数据结构中添加元素是很搞笑的,直接放在数据末尾的第一个空位就可以。
缺点:向集合插入元素将会变得低效,他需要给插入的元素腾出位置并顺序移动后面的元素。
顺序存储
即线性表。可以动态的扩大和缩小,他在一片连续的区域中存储数据元素。线性表不能按照索引进行查找,
它是通过对地址的引用来搜索元素的,为了找到某个元素,他必须遍历所有元素,直到找到对应的元素为止。
优点:插入,删除效率高。
缺点:查找的效率相对低一些。
a.队列Queue,先进先出。
b.栈Stack,先进后出。
c.字典Dictionary,键值对。
d.双向链表 LinkedList<T>, 是一个类型为LinkedListNode的元素对象的集合、当我们需要在集合中插入,删除要求
快的时候,可以使用。
4.确保集合的线程安全
foreach循环不能代替for新欢一个重要原因居室在迭代过程中第集合本身进行了增删操作。将此场景
移值到多线程场景中:确保集合的线程安全:集合线程安全是指在多个线程中添加或删除元素时,线程之间
必须保持同步。
5.理解延迟求值和主动求值

在延迟执行求值的情况,只是定义了一个查询,而不是立刻执行。对查询结果的访问每次都hi遍历原集合。对
调用ToList,ToArray等方法,将会使其立刻执行。

浙公网安备 33010602011771号