2013-07-30 38 views
2

我試圖開發一個實現IComparable的泛型類「MinHeap(T)」。當泛型爲「int」或其他類「代碼」時,它工作正常。進一步使用T的泛型類「節點(代碼)」 會導致下面提到的錯誤。泛型和IComparable - 錯誤CS00301

我可能太新,不瞭解IComparable和IComparable(T)之間的微妙差異。有人有想法嗎? 預先感謝您的幫助, LJ

public class MinHeap<T> where T : IComparable 
{ 
... 
} 
public class Node<T> where T : IComparable 
{ 
    T data 
... 
    public int CompareTo(object obj) 
    { 
     Node<T> otherNode = obj as Node<T>; 
     return this.data.CompareTo(otherNode.data); 
    } 
... 
} 
public class Code : IComparable 
{ 
    public int freq; 
... 
    public int CompareTo(object obj) 
    { 
     Code otherCode = obj as Code; 
     return this.freq.CompareTo(otherCode.freq); 
    } 
} 
static void Main(string[] args) 
{ 
    MinHeap<int> hInt = new MaxHeap<int>(heapSeed); // works fine 
    MinHeap<Code> hCode = new MinHeap<Code>(codeList); // works fine 
... 
    Node<Code>[] nodeCodeList = new Node<Code>[freqList.Length]; // ok   
    MinHeap<Node<Code>> h = new MinHeap<Node<Code>>(nodeCodeList); // Error 
... 
} 

錯誤消息:

錯誤2類型 'Algorithms.Node(Algorithms.Code)' 不能被用作類型參數 'T' 在泛型類型或方法'Algorithms.MinHeap(T)'。沒有從'Algorithms.Node(Algorithms.Code)'到'System.IComparable'的隱式引用轉換。

+0

'T'不僅應該可比,'節點'也應該是。 – leppie

+0

以下應該工作:'公共類節點:IComparable其中T:IComparable'。 MinHeap也一樣。 @Aphelion有解釋。 – leppie

+0

現在工作正常 - 這是沒有必要做同樣的MinHeap - 非常感謝 – CSJNL

回答

2

Node<T>類不執行IComparable。它只對T的類型有約束。

看起來您已嘗試實施decorator模式。實現接口,然後將這些方法映射到裝飾對象。

+0

MinHeap 不必實現IComparable。 – empi

+0

@empi謝謝!我修改了答案。 – Aphelion

+0

按建議修改的代碼@leppie 感謝所有 – CSJNL

1

你應該實現Node類內IComparable接口,就像這樣:

public class Node<T>: IComparable<Node<T>> // <- IComparable<Node<T>> implemented 
    where T: IComparable { 

    T data; 

    ... 

    #region IComparable<Node<T>> Members 

    // interface implementation, not just a method 
    public int CompareTo(Node<T> other) { 
     // Let us be accurate with possible nulls: 
     if (Object.ReferenceEquals(null, other)) 
     return 1; // <- or -1 if you think it's right 
     else if (Object.ReferenceEquals(data, other.data)) 
     return 0; 
     else if (Object.ReferenceEquals(null, data)) 
     return -1; // <- or 1 if you think it's right 

     return data.CompareTo(other.data); 
    } 

    #endregion IComparable<Node<T>> Members 
    } 

根據最小堆的算法,你可能有MinHeap類實現IComparable>以及

+0

我想你需要首先執行'ReferenceEquals(data,other.data)'。否則,如果'other.data == null',即使'this.data == null',它總是*返回-1。 –

+0

對不起,但是ReferenceEquals(data,other.data)不能是第一個。如果其他是空的呢?在這種情況下,other.data會拋出異常。 –

+0

啊,你說得對。我誤解了代碼。 –

2

你可能最好定義你的泛型類,以便它不需要需要該類型實現IComparable<T>。這就是.NET通用類的實現方式。他們將使用默認的比較的類型,或者使用在通過IComparer<T>例如,SortedList有這些構造函數(其中包括):

SortedList<TKey, TValue>(); // uses default comparer for TKey 
SortedList<TKey, TValue>(IComparer<T> comparer); // uses supplied comparer 

這是很容易實現:

public class MinHeap<T> 
{ 
    private IComparer<T> _comparer; 

    public MinHeap<T>(IComparer<T> comp) 
    { 
     _comparer = comp; 
    } 

    public MinHeap<T>() 
     : this(Comparer<T>.Default) 
    { 
    } 
} 

這樣,您的客戶可以使用MinHeap<T>來保存不執行IComparable<T>的類的實例。

當你做你的比較,你叫_comparer.Compare(item1, item2)

在另一方面,有對你的堆無需特別要求的節點。您可以在數組中實現二進制堆。參見例如A Generic BinaryHeap Class