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等方法,将会使其立刻执行。

posted @   不三周助  阅读(305)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示