C # Generics: Вставка T как конфликт интерфейса T: IComparable <T> - PullRequest
1 голос
/ 25 августа 2010

Это задача для мастеров шаблонов / шаблонов проектирования C #.

Я пытаюсь реализовать общую кучу, а затем очередь приоритетов, которая использует кучу.

Моя кучаподпись:

class Heap<TKey, TValue> where TKey : IComparable<TKey>

Мой класс очереди приоритетов:

public delegate IComparable<T> Evaluator<T>(T item);

class PriorityQueue<T> : IQueue<T>
{
    Evaluator<T> Evaluate;
    Heap<IComparable<T>, T> m_heap;

    public PriorityQueue(Evaluator<T> evaluateFunction)
    {
        Evaluate = evaluateFunction;
        m_heap = new Heap<int, T>(HeapType.MinHeap);
    }

    ...

    public void Insert(T element)
    {
        m_heap.Insert(Evaluate(element), element);
    }

    ...

Но при этом компилятор (оправданно) жалуется, что ICompareble не реализует интерфейс ICompareble, следовательно

Heap<IComparable<T>, T> m_heap;

конфликтует с

where TKey : IComparable<TKey>

Что вы можете сделать, чтобы решить эту проблему?!

полная ошибка компилятора:

The type 'System.IComparable<T>' cannot be used as type parameter 'TKey' in the generic type or method 'Heap<TKey,TValue>'. There is no implicit reference conversion from 'System.IComparable<T>' to 'System.IComparable<System.IComparable<T>>'.

Ответы [ 3 ]

4 голосов
/ 25 августа 2010

Ваша реализация довольно запутанная. Мне кажется, этого достаточно:

// replaces existing Evaluator signature.  I would personally ditch this
// definition and just use Func<TValue, TKey> instead
public delegate TKey Evaluator<TKey, TValue>(TValue item);

class PriorityQueue<T>
{
    Evaluator<int, T> Evaluate;
    Heap<int, T> m_heap;

    public PriorityQueue(Evaluator<int, T> evaluateFunction)
    {
        Evaluate = evaluateFunction;
        m_heap = new Heap<int, T>(HeapType.MinHeap);
    }

    public void Insert(T element)
    {
        m_heap.Insert(Evaluate(element), element);
    }
}

Есть ли какая-то причина, по которой приоритетная очередь должна иметь общий ключ? Если это так, то вам следует вместо этого указать PriorityQueue<TKey, TValue> и заменить int на TKey, добавив ограничение, TKey : IComparable<TKey> (как в подписи вашей кучи).

По сути, определение вашей очереди приоритетов должно выглядеть как определение вашей кучи, если вы хотите, чтобы ключ был любого типа, или таким же, но не параметризованным для типа ключа.

0 голосов
/ 25 августа 2010

Я думаю, было бы намного лучше, если бы вы полагались на IComparer<T>, а не на Evaluator<T> делегата.В любом случае, как прямой ответ на ваш вопрос:

class Heap<TKey, TValue> where TKey : IComparable<TKey> { }

public delegate TOutput Evaluator<TInput, TOutput>(TInput item) where TOutput : IComparable<TOutput>;

class PriorityQueue<TInput, TTransformComparable> where TTransformComparable : IComparable<TTransformComparable>
{
    Evaluator<TInput, TTransformComparable> Evaluate;
    Heap<TTransformComparable, TInput> m_heap;

    public PriorityQueue(Evaluator<TInput, TTransformComparable> evaluateFunction)
    {
        Evaluate = evaluateFunction;
        m_heap = new Heap<TTransformComparable, TInput>(HeapType.MinHeap);
    }     

    public void Insert(TInput element)
    {
        m_heap.Insert(Evaluate(element), element);
    }    
}
0 голосов
/ 25 августа 2010

Я думаю, если вы замените ..

class Heap<TKey, TValue> where TKey : IComparable<TKey>

.. с ..

class Heap<TKey, TValue> where TKey : IComparable<TValue>

.. это будет работать так, как вы собираетесь.

...