问题
您希望通过将所有Stack和Queue对象替换为相应泛型版本以提高应用效率并使得代码更易于使用当结构体或其他值类型存储在这些数据结构中时会导致装箱/拆箱操作这时就需要这么做
解决方案
使用.Collections.Generic.Stack和.Collections.Generic.Queue对象来替换现有.Collections.Stack和.Collections.Queue对象
这里有个简单地使用.Collections.Queue对象简单例子:
public void UseNonGenericQueue
{
// 创建个非泛型队列对象
Queue numericQueue = Queue;
// 进队(导致装箱操作).
numericQueue.Enqueue(1);
numericQueue.Enqueue(2);
numericQueue.Enqueue(3);
//出队并显示项(导致拆箱操作)
Console.WriteLine(numericQueue.Dequeue);
Console.WriteLine(numericQueue.Dequeue);
Console.WriteLine(numericQueue.Dequeue.);
}
下面是相同代码使用了.Collections.Generic.Queue对象
public void UseGenericQueue
{
// 创建个泛型队列对象.
Queue<> numericQueue = Queue<>;
// 进队.
numericQueue.Enqueue(1);
numericQueue.Enqueue(2);
numericQueue.Enqueue(3);
// 出队并显示项目.
Console.WriteLine(numericQueue.Dequeue);
Console.WriteLine(numericQueue.Dequeue);
Console.WriteLine(numericQueue.Dequeue);
}
下面是个简单地使用.Collections.Stack对象例子
public void UseNonGenericStack
{
// 创建个非泛型栈.
Stack numericStack = Stack;
// 进栈(导致装箱操作).
numericStack.Push(1);
numericStack.Push(2);
numericStack.Push(3);
// 出栈并显示项目(导致拆箱操作).
Console.WriteLine(numericStack.Pop.);
Console.WriteLine(numericStack.Pop.);
Console.WriteLine(numericStack.Pop.);
}
下面是相同代码使用了.Collections.Generic.Stack对象
public void UseGenericStack
{
// 创建个泛型栈对象.
Stack<> numericStack = Stack<>;
// 进栈.
numericStack.Push(1);
numericStack.Push(2);
numericStack.Push(3);
// 出栈并显示项目.
Console.WriteLine(numericStack.Pop.);
Console.WriteLine(numericStack.Pop.);
Console.WriteLine(numericStack.Pop.);
}
讨论
表面上泛型和非泛型Queue和Stack类非常相象但在内部机制上却有极大地区别除了例子化对象的外泛型版Queue和Stack和非泛型版Queue和Stack使用是基本相同泛型结构为了创建个类型需要个类型参数在此例中类型参数是这个类型参数表明Queue和Stack对象将只能包含整数类型和能够被隐式转换为整数类型比如类型:
s = 300;
numericQueue.Enqueue(s); // 成功进行了隐式转换
但如果个类型不能被隐式转换为整数如double将会导致个编译期
double d = 300;
numericQueue.Enqueue(d); // 不能进行隐式转换
numericQueue.Enqueue(()d); // 成功进行了显式转换
非泛型结构不需要类型参数非泛型版Queue和Stack对象只能包含Object类型(译者注:任何对象都可以隐式转换为Object并于这点有不清楚请参考:
http://cgbluesky.blog.163.com/blog//24123558200712493419458/ )
当需要在Queue或Stack泛型版和非泛型版做出选择时您需要决定使用强类型Queue或Stack对象(也就是泛型版Queue或Stack类)还是弱类型Queue或Stack对象(也就是非泛型版Queue或Stack类)选择泛型版Queue或Stack类相对于非泛型版来说会提供很多好处包括:
类型安全
包含在数据结构中每个元素都是指定类型这意味着当在数据结构中进行添加或删除操作时不再需要将它们转换成object类型您不能在个单数据结构中存储多种区别类型;您总是知道数据结构中存储是什么类型在编译期进行类型检查优于在运行期进行检查可以归结为更简洁代码更好性能更少
缩短开发周期
创建个类型安全数据结构而不使用泛型意味着不得不从.Collections.Stack或.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对象来说这非常容易实现代码如下:
public void CloneQueue
{
// 创建个Queue对象.
Queue<> numericQueue = Queue<>;
// 进队
numericQueue.Enqueue(1);
numericQueue.Enqueue(2);
numericQueue.Enqueue(3);
// 创建个克隆numericQueue.
Queue<> clonedNumericQueue = Queue<>(numericQueue);
// 这只是简单地看下里面值并非出队
foreach ( i in clonedNumericQueue)
{
Console.WriteLine("foreach: " + i.);
}
// 出队并显示项目
Console.WriteLine(clonedNumericQueue.Dequeue.);
Console.WriteLine(clonedNumericQueue.Dequeue.);
Console.WriteLine(clonedNumericQueue.Dequeue.);
}
思路方法输出结果如下:
foreach: 1
foreach: 2
foreach: 3
1
2
3
对于Stack对象其代码如下:
public void CloneStack
{
// 创建个泛型Stack对象
Stack<> numericStack = Stack<>;
// 进栈
numericStack.Push(1);
numericStack.Push(2);
numericStack.Push(3);
// 克隆numericStack 对象.
Stack<> clonedNumericStack = Stack<>(numericStack);
// 这只是简单地看下里面值并非出栈
foreach ( i in clonedNumericStack)
{
Console.WriteLine("foreach: " + i.);
}
// 出栈并显示项目
Console.WriteLine(clonedNumericStack.Pop.);
Console.WriteLine(clonedNumericStack.Pop.);
Console.WriteLine(clonedNumericStack.Pop.);
}
思路方法输出结果如下:
foreach: 1
foreach: 2
foreach: 3
1
2
3
构造思路方法创建了个新Queue或Stack例子并包含了Ienumerable<T>类型中所有元素份拷贝
最新评论