2013-07-30 3 views
2

Я попытался разработать универсальный класс «MinHeap (T)», реализующий IComparable. Он отлично работает, когда generic является «int» или другим классом «Code». Далее и используя для T общий класс «Node (Code)» приводит к ошибке, упомянутой ниже.Generics и 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)' не может быть использована в качестве параметра типа 'Т' в общий тип или метод «Алгоритмы.MinHeap (T)». Нет никакого неявного ссылочного преобразования из «Алгоритмы.Node (Алгоритмы.Код)» в «System.IComparable».

+0

'T' должно быть не только сопоставимым,' Узел 'тоже должен быть. – leppie

+0

Следующее должно работать: 'public class Node : 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

Вы должны реализовать интерфейс IComparable внутри класса Node, как это:

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 
    } 

в зависимости от алгоритма мин кучи, вы, возможно, придется реализовать IComparable> в классе MinHeap а

+0

Я думаю, вам нужно сначала выполнить 'ReferenceEquals (data, other.data)'. В противном случае он всегда будет возвращать -1, если 'other.data == null', даже если' this.data == null'. –

+0

Извините, но ReferenceEquals (data, other.data) не может быть первым. Что, если другое значение равно null? В этом случае 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.

Смежные вопросы