我发现不止一次需要将泛型集合在一个时间点作为列表处理,在另一个时间作为堆栈或队列处理。对于我正在开发的应用程序,使用三个单独的对象没有意义。
我能想到的最简单的解决方案是在标准列表上实现Queue / Dequeue / Push / Pop / Peek功能。另外(未包含在下面的代码中),在T上应用了接口约束,允许类维护每个列表,队列和堆栈的位置/序数索引。
public class List<T>:
System.Collections.Generic.List<T>
{
private object SyncRoot = new object();
public void Enqueue (T item)
{
lock (this.SyncRoot)
{
this.Add(item);
}
}
public T Dequeue ()
{
T item = default(T);
lock (this.SyncRoot)
{
if (this.Count > 0)
{
item = this [0];
this.RemoveAt(0);
}
}
return (item);
}
public void Push (T item)
{
lock (this.SyncRoot)
{
this.Add(item);
}
}
public T Pop ()
{
T item = default(T);
lock (this.SyncRoot)
{
if (this.Count > 0)
{
item = this [this.Count - 1];
this.RemoveAt(this.Count - 1);
}
}
return (item);
}
public T PeekQueue ()
{
T item = default(T);
lock (this.SyncRoot)
{
if (this.Count > 0)
{
item = this [0];
}
}
return (item);
}
public T PeekStack ()
{
T item = default(T);
lock (this.SyncRoot)
{
if (this.Count > 0)
{
item = this [this.Count - 1];
}
}
return (item);
}
}
答案 0 :(得分:2)
以下是如何使用扩展方法来实现类似行为... http://weblogs.asp.net/bsimser/archive/2011/01/13/generic-pop-and-push-for-list-lt-t-gt.aspx
Generic Pop and Push for List
这是我用来扩展通用List类的小片段 与Stack类相似的功能。
Stack类很棒,但它存在于自己的世界之下 System.Object的。拥有可以执行此操作的List是不是很好 相同?这是代码:
public static class ExtensionMethods
{
public static T Pop<T>(this List<T> theList)
{
var local = theList[theList.Count - 1];
theList.RemoveAt(theList.Count - 1);
return local;
}
public static void Push<T>(this List<T> theList, T item)
{
theList.Add(item);
}
}
这是一个简单的扩展,但我发现它很有用,希望你能 太!享受。
也是扩展方法的链接 http://msdn.microsoft.com/en-us/library/bb383977.aspx
答案 1 :(得分:0)
我猜你必须使用数组作为内部数据存储,如何在.NET List和其他泛型中实现它。例如,由于无法处理itnernal数组中的所有元素而不是开始索引移动,因此代码出列效率低下。人们可以在ILSpy中看到C#反编译:
// System.Collections.Generic.List<T>
/// <summary>Removes the element at the specified index of the <see cref="T:System.Collections.Generic.List`1" />.</summary>
/// <param name="index">The zero-based index of the element to remove.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="index" /> is less than 0.-or-<paramref name="index" /> is equal to or greater than <see cref="P:System.Collections.Generic.List`1.Count" />.</exception>
public void RemoveAt(int index)
{
if (index >= this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
this._size--;
if (index < this._size)
{
Array.Copy(this._items, index + 1, this._items, index, this._size - index);
}
this._items[this._size] = default(T);
this._version++;
}
其他功能也可以改进一点。
此外,我注意到.NET Stack通用实现比List通用实现工作缓慢。我假设这是因为分配时提取的最后一个元素的默认值,与List:
不同// System.Collections.Generic.Stack<T>
/// <summary>Removes and returns the object at the top of the <see cref="T:System.Collections.Generic.Stack`1" />.</summary>
/// <returns>The object removed from the top of the <see cref="T:System.Collections.Generic.Stack`1" />.</returns>
/// <exception cref="T:System.InvalidOperationException">The <see cref="T:System.Collections.Generic.Stack`1" /> is empty.</exception>
public T Pop()
{
if (this._size == 0)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyStack);
}
this._version++;
T result = this._array[--this._size];
this._array[this._size] = default(T);
return result;
}