2012-09-20 34 views
2

我發現不止一次,泛型集合需要在某個時間點被視爲列表,在另一個時間點被視爲棧或隊列。對於我正在開發的應用程序,使用三個單獨的對象是沒有意義的。實現自定義通用列表/隊列/堆棧組合的有效方式

我能想到的最簡單的解決方案是在標準列表上實現隊列/出隊/推/流行/窺視功能。另外(不包括在下面的代碼中),在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); 
    } 
} 
  • 由於這是一個粗略的,在即時實現,我不知道要尋找什麼角落的情況下出了那麼將不勝感激指針或鏈接到任何現有的這樣的實現。其次,我對非常大的名單上的表現持懷疑態度。是否決定從列表繼承,而不是使用說LinkedList的大列表。在我的情況下,添加/刪除項目的優先級高於枚舉列表。
+0

注:我也知道這樣一類不會讓供其他開發人員使用的一個很好的候選人,因爲相結合的列表,隊列和棧的功能可以說是相當反直覺取決於你如何使用它們。 –

+0

http://weblogs.asp.net/bsimser/archive/2011/01/13/generic-pop-and-push-for-list-lt-t-gt。aspx – hagensoft

+0

@hagensoft:我似乎無法訪問頁面內容。它只能部分加載。你可以在這裏粘貼要點嗎? –

回答

2

下面是如何acomplish與擴展方法類似的操作... http://weblogs.asp.net/bsimser/archive/2011/01/13/generic-pop-and-push-for-list-lt-t-gt.aspx

通用Pop和Push for List

下面是我用來擴展一個通用List類的小片段,使其具有與Stack類相似的功能 。

Stack類很不錯,但它在 System.Object下生活在它自己的世界裏。有一個可以做 的列表是不是很好?下面的代碼:

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

0

我想你必須使用數組作爲內部數據存儲,它是如何在.NET List和其他泛型中實現的。例如,由於對內部數組中的所有元素無用的處理,而不是啓動索引移動,因此您的代碼出隊效率低下。在C#反編譯中可以看到ILSpy:

// 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通用實現慢。我想這是因爲分配新建分配FY的默認值棧的最後一個元素,同時提取,不像清單:

// 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; 
}