4.5 使用相应的泛型版本替换Stack和Queue
问题
您希望通过将所有Stack和Queue对象替换为相应的泛型版本以提高应用程序的效率,并使得代码更易于使用。当结构体或其他值类型存储在这些数据结构中时,会导致装箱/拆箱操作,这时就需要这么做。
解决方案
使用System.Collections.Generic.Stack和System.Collections.Generic.Queue对象来替换现有的System.Collections.Stack和System.Collections.Queue对象。
这里有一个简单地使用System.Collections.Queue对象的简单例子:














下面是相同的代码使用了System.Collections.Generic.Queue对象














下面是一个简单地使用System.Collections.Stack对象的例子














下面是相同的代码使用了System.Collections.Generic.Stack对象














讨论
表面上,泛型和非泛型的Queue和Stack类非常相象。但在内部机制上却有极大地不同。除了实例化对象之外,泛型版的Queue和Stack和非泛型版的Queue和Stack的使用是基本相同的。泛型结构为了创建一个类型需要一个类型参数。在此例中,类型参数是int。这个类型参数表明Queue和Stack对象将只能包含整数类型和能够被隐式转换为整数的类型,比如short类型:



但如果一个类型不能被隐式转换为整数,如double,将会导致一个编译期错误。




非泛型结构不需要类型参数,因为非泛型版的Queue和Stack对象只能包含Object类型。(译者注:任何对象都可以隐式转换为Object,并于这一点有不清楚的请参考:
http://cgbluesky.blog.163.com/blog/static/24123558200712493419458/ )
当需要在Queue或Stack的泛型版和非泛型版做出选择时,您需要决定使用强类型Queue或Stack对象(也就是泛型版Queue或Stack类)还是弱类型的Queue或Stack对象(也就是非泛型版Queue或Stack类)。选择泛型版Queue或Stack类相对于非泛型版来说会提供很多好处,包括:
类型安全
包含在数据结构中的每个元素都是指定的类型。这意味着当在数据结构中进行添加或删除操作时不再需要将它们转换成object类型。您不能在一个单一数据结构中存储多种不同的类型;您总是知道数据结构中存储的是什么类型。在编译期进行类型检查优于在运行期进行检查。可以归结为更简洁的代码,更好的性能,更少的错误。
缩短开发周期
创建一个类型安全的数据结构而不使用泛型意味着不得不从System.Collections.Stack或System.Collections.Queue继承创建自己的子类,这是一个耗时并容易发生错误的工作。而泛型只需您在编译期简单地告诉Queue或Stack对象控制什么类型。
性能
使用泛型Queue或Stack在添加和删除元素时避免了潜在的费时的类型转换的发生。另外在把值类型添加进Queue或Stack时不会发生装箱操作,从Queue或Stack删除值类型时也不会发生拆箱操作。
容易阅读的代码
您的基础代码将变得非常少,因为不再需要从非泛型版的Queue或Stack类继续创建您自己的强类型类。另外泛型代码的类型安全功能将使在代码中使用Queue或Stack类的目的变得更容易理解。
泛型版和非泛型版的Queue和Stack的不同之处在于两种类之间的成员实现。在非泛型版实现而在泛型版没有实现的成员列表如下:
Clone 方法
IsSynchronized 属性
SyncRoot 属性
Synchronized 方法
非泛型版Queue和Stack类中存在Clone方法是因为只有它实现了Icolneable接口。但非泛型版Queue和Stack类实现的其他接口是一样的。
一个弥补泛型版Queue和Stack类中不存在Clone方法的途径是接收一个Ienumerable<T>类型。因为这是Queue和Stack类实现的接口之一,对于Queue对象来说,这非常容易实现,代码如下:





















方法的输出结果如下:
foreach: 1
foreach: 2
foreach: 3
1
2
3
对于Stack对象,其代码如下:





















方法的输出结果如下:
foreach: 1
foreach: 2
foreach: 3
1
2
3
构造方法创建了一个新的Queue或Stack实例,并包含了Ienumerable<T>类型中所有元素的一份拷贝。
阅读参考
查看MSDN文档中的“System.Collections.Stack Class”, “System.Collections.Generic.Stack Class”, “System.Collections.Queue Class”和“System.Collections.Generic.Queue Class”主题。