翼度科技»论坛 编程开发 .net 查看内容

C#.Net筑基-集合知识全解

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21

01、集合基础知识

.Net 中提供了一系列的管理对象集合的类型,数组、可变列表、字典等。从类型安全上集合分为两类,泛型集合非泛型集合,传统的非泛型集合存储为Object,需要类型转。而泛型集合提供了更好的性能、编译时类型安全,推荐使用。
.Net中集合主要集中在下面几个命名空间中:

1.1、集合的起源:接口关系


集合接口特点/说明IEnumerator、IEnumerator枚举器(还不是集合),提供foreach枚举项的能力IEnumerable、IEnumerable可枚举集合,几乎所有集合都实现了该接口,属于集合最基础的接口。就一个IEnumerator GetEnumerator() 方法,返回一个枚举器。ICollection、ICollection提供了基础集合操作:Count、Add()、Remove()、Clear()、Contains()、CopyTo()IList、IList索引器[int index]、IndexOf()、Insert()、RemoveAt()IDictionary、IDictionary键值集合操作:Keys、Values、索引器[Key]、Add()、Remove()IReadOnly***只读的集合,包括IReadOnlyCollection、IReadOnlyList、IReadOnlyDictionary等

  • 天赋技能 —— foreach:几乎所有集合都可以用foreach循环操作,是因为他们都继承自IEnumerable接口,由枚举器(IEnumerator)提供枚举操作。
  • 几乎所有集合都提供添加、删除、计数,来自基础接口 ICollection、ICollection。
  • IList、IList 提供了数组的索引器、查找、插入等操作,几乎所有具体的集合类型都实现了该接口。
  • Array 是一个抽象类,是所有数组T[]的基类,她是类型安全的。
  • 推荐尽量使用数组T[]、泛型版的集合,提供了更好的类型安全和性能。

1.2、非泛型集合—— 还有什么存在的价值?


  • 非泛型的Hashtable,Key、Value都是Object类型的,Dictionary 是泛型版本的 Hashtable。
  • ArrayList 是非泛型版本的 List,基本很少使用,也尽量不用。
❓既然非泛型版本类型不安全,性能还差,为什么还存在呢?
主要是历史原因,泛型是.Net2.0 引入的,因此为了向后兼容,依然保留的非泛型版本集合。在接口实现时,非泛型接口一般都是显示实现的,因此基本不会用到。不过在有些场景下,非泛型接口、集合还是有点用的,如类型不固定的集合,或者用接口作为约束条件或类型判断。
  1. ArrayList arr = new ArrayList();
  2. arr.Add(1);
  3. arr.Add("sam");
  4. arr.Add(new Point());
  5. if (arr is IList) {}
  6. class User<T> where T :IList {}
复制代码
1.3、Collection、List有何不同?

❓两者比较相似,他们到底有什么区别呢?该如何选择?

  • Collection 作为自定义集合基类,内部提供了一些virtual的实现,便于继承实现自己的集合类型。其内部集合用的就是List,如下部分源码 Collection.cs。
  • List 作为集合使用,是最常用的可变长集合类型了,他优化了性能,但是丢失了可扩展性,没有提供任何可以override的成员。
  1. public class Collection<T>
  2. {
  3.     public Collection()
  4.     {
  5.         items = new List<T>();
  6.     }
  7.     protected virtual void InsertItem(int index, T item)
  8.     {
  9.         items.Insert(index, item);
  10.     }
  11. }
复制代码
02、枚举器——foreach的秘密!

foreach 用来循环迭代可枚举对象,用一种非常简洁、优雅的姿势访问可枚举元素。常用于数组、集合,当然不仅限于集合,只要符合要求枚举要求的都可以。
foreach 可枚举类型说明数组包括Array数组、List、字典等,他们都实现了IEnumerable接口的。IEnumerable可枚举接口IEnumerable同上,泛型版本GetEnumerator()方法包含公共方法“IEnumerator GetEnumerator();”的任意类型yield迭代器yield语句实现的迭代器,实际返回的也是IEnumerable、IEnumerator


2.1、IEnumerator枚举器

枚举可以foreach 枚举的密码是他们都继承自IEnumerable接口,而更重要的是其内部的枚举器 —— IEnumerator。枚举器IEnumerator定义了向前遍历集合元素的基本协议,其申明如下:
  1. public interface IEnumerator
  2. {
  3.         object Current { get; }
  4.         bool MoveNext();
  5.         void Reset();  //这个方法是非必须的,用于重置游标,可不实现
  6. }
  7. public interface IEnumerator<out T> : IDisposable, IEnumerator
  8. {
  9.         new T Current { get; }
  10. }
复制代码

  • MoveNext() 移动当前元素到下一个位置,Current获取当前元素,如果没有元素了,则MoveNext()返回false。注意MoveNext()会先调用,因此首次MoveNext()是把位置移动到第一个位置。
  • Reset()用于重置到起点,主要用于COM互操作,使用很少,可不用实现(直接抛出 NotSupportedException)。
<blockquote>

来源:https://www.cnblogs.com/anding/p/18229596
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具