【 tulaoshi.com - ASP.NET 】
范型集合 毫无疑问,范型最典型的应用莫过于范型集合了。在 .NET 2.0 中提供了已有集合类和接口的范型版本,它们位于 System.Collections.Generic 命名空间中。 .NET 2.0 中新的范型集合类并不是简单的在已有非范型集合类的设计上多加了个范型参数 T 而已。新的范型集合类的设计充分吸收了已有设计中的合理之处并摒弃了一些不甚合理之处,同时引入了新的针对范型的设计。所以,新的范型类和接口的设计应该更加合理和有效,不过 .NET 程序员则需要花些时间学习新的设计并了解与已有设计有什么样的不同,以及在将代码从非范型集合移植到范型集合时可能会出现的兼容性问题。 下面是范型集合和已有非范型集合的对照表(不全): 非范型接口 范型接口 非范型类 范型类 IEnumerator IEnumerator
ArrayList List IEnumerable IEnumerable Stack Stack ICollection ICollection Queue Queue IList IList DictionaryEntry KeyValuePair IDictionary IDictionary Hashtable Dictionary IComparable IComparable Comparer Comparer IComparer IComparer 可以看到,部分类的名字做了修改,例如 ArrayList 现在改为 List,Hashtable 改为 Dictionary,DictionaryEntry 改为 KeyValuePair 等等。这样的命名当然更加合理(因为 IList 是接口,List 是对应的具体类;同样 IDictionary 是接口, Dictionary 是对应的具体类;而 KeyValuePair 显然比 DictionaryEntry 更加容易理解和记忆),但对已经习惯了以前的命名的程序员来说可能一开始会有点找不找北的感觉。 前面说过,新的范型集合接口/类和以前的非范型版本相比有较大的设计改变,下面我们来看看这些变化。 IEnumerator IEnumerator/IEnumerator 接口允许对一个集合进行遍历,主要用在 .NET 编程语言的遍历语句中,例如 C# 的 foreach 语句。用户代码通常不直接使用这个接口。IEnumerator 和非范型版本 IEnumerator 相比去掉了 Reset 方法。这可能是出于以下考虑: l IEnumerator 接口主要设计用于支持诸如 foreach 这样的语句,而这些地方用不到 Reset 方法。去掉 Reset 方法使得设计更加简化并降低了实现该接口的难度。如果调用者需要类似 Reset 的功能,可以重新获取一个枚举器(例如通过调用 GetEnumerator 方法)。 l C# 2.0 Iterators 提供了自动生成枚举器的方法,编译器自动为指定的类实现 IEnumerator 接口和 IEnumerator 接口。而对IEnumerator 接口的 Reset 方法的实现只是简单的抛出 System.NotSupportedException 异常。所以在 IEnumerator 的设计中移去 Reset 方法显得非常自然和合理。 ICollection ICollection 接口的设计和非范型版本 ICollection 相比改变很大。ICollection 接口的最初设计意图是支持复制集合元素(通过 Count 属性和 CopyTo 方法),以及支持同步访问模式(通过 IsSynchronized 属性和 SyncRoot 属性)。ICollection 的设计保留了对复制集合元素的支持,但是摒弃了对同步访问模式的支持,这是因为实践证明 ICollection 的同步访问模式是让人困惑和低效的。不少刚学 .NET 的程序员一开始搞不懂 SyncRoot 是个什么东东,有什么用。另外,从性能和逻辑上考虑,何时锁定集合应该由调用者决定,而不是由实现者决定。所以总的来说 IsSynchronized 和 SyncRoot 不是很理想的设计。因此,ICollection 没有 IsSynchronized 属性和 SyncRoot 属性。 除此之外,ICollection 还增加了一些新的属性和方法,它们让 ICollection 接口变得更加有用。这些属性和方法事实上是从 IList 和 IDictionary 的共同属性和方法移植过来的,包括: l IsReadOnly,用于判断集合是否是只读的。 l Add/Remove/Clear,用于对集合元素进行管理。这些方法对列表和字典都是有效的。 l Contains,用于判断集合中是否包含指定的值。 另外,对于一些不需要更改集合的使用情景来说,提供一个类似 IReadOnlyCollection 这样的接口可能会有意义,它只需要支持 Count 属性,CopyTo 方法和 Contains 方法即可。然而微软并没有采用这样的设计,主要理由是为了使基本集合接口尽量简单和易用。微软的建议是程序员需要的话自己定义这样的接口。 IList 和 List 刚才提到,IList 相对于 IList 的变化是通用的属性和方法被移植入 ICollection 了,仅剩下对列表有效的基于索引访问的属性和方法。 List 相对 ArrayList 来讲也做了很大的设计改变。做出这些改变的主要考虑是性能,因为动态数组是 .NET 程序使用的最基本的数据结构之一,它的性能影响到应用程序的全局。例如,以前 ArrayList 默认的 Capacity 是 16,而 List 的默认 Capacity 是 4,这样可以尽量减小应用程序的工作集。另外,List 的方法不是虚拟方法(ArrayList 的方法是虚拟方法),这样可以利用函数内联来提高性能(虚函数不可以被内联)。List 也不支持问题多多的 Sync