Проблемы с реализацией универсального IEnumerator и IComparable - PullRequest
3 голосов
/ 15 мая 2010

Я работаю над деревом AVL. Кажется, что само дерево работает, но мне нужен итератор для просмотра значений дерева. Поэтому я попытался реализовать взаимодействие IEnumerator. К сожалению, я получаю ошибку времени компиляции, реализующую IEnumerator и IComparable. Сначала код, а ниже - ошибка.

class AvlTreePreOrderEnumerator<T> : IEnumerator<T> where T :IComparable<T>
{
    private AvlTreeNode<T> current = default(T);
    private AvlTreeNode<T> tree = null;
    private Queue<AvlTreeNode<T>> traverseQueue = null;

    public AvlTreePreOrderEnumerator(AvlTreeNode<T> tree)
    {
        this.tree = tree;

        //Build queue
        traverseQueue = new Queue<AvlTreeNode<T>>();
        visitNode(this.tree.Root);
    }

    private void visitNode(AvlTreeNode<T> node)
    {
        if (node == null)
            return;
        else
        {
            traverseQueue.Enqueue(node);
            visitNode(node.LeftChild);
            visitNode(node.RightChild);
        }
    }

    public T Current
    {
        get { return current.Value; }
    }

    object IEnumerator.Current
    {
        get { return Current; }
    }

    public void Dispose()
    {
        current = null;
        tree = null;
    }

    public void Reset()
    {
        current = null;
    }

    public bool MoveNext()
    {
        if (traverseQueue.Count > 0)
            current = traverseQueue.Dequeue();
        else
            current = null;

        return (current != null);
    }
}

Ошибка от VS2008: Ошибка 1 Тип «T» нельзя использовать в качестве параметра типа «T» в универсальном типе или методе «Opdr2_AvlTreeTest_Final.AvlTreeNode». Конвертирование или преобразование параметров типа из 'T' в 'System.IComparable' не выполняется.

Эта ошибка указана в следующих строках:

    //members
    private AvlTreeNode<T> current = default(T);  //current highlighted
    private AvlTreeNode<T> tree = null;   //tree highlighted
    private Queue<AvlTreeNode<T>> traverseQueue = null;   //traverseQueue highlighted  

    //Constructor
    public AvlTreePreOrderEnumerator(AvlTreeNode<T> tree)  // AvlTreePreOrderEnumerator highlighted  
    //Method
    private void visitNode(AvlTreeNode<T> node)   //visitNode highlighted  

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

Thx!

Ответы [ 4 ]

2 голосов
/ 15 мая 2010

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

public class AvlTreeNode<T> where T : IComparable<AvlTreeNode<T>> {
    public AvlTreeNode<T> Root;
    public AvlTreeNode<T> LeftChild {get;set;}
    public AvlTreeNode<T> RightChild {get;set;}
    public T Value { get; set;}
}

Попробуйте это (измененный тип параметра IComparable):

public class AvlTreeNode<T> where T : IComparable<T> {
    public AvlTreeNode<T> Root;
    public AvlTreeNode<T> LeftChild {get;set;}
    public AvlTreeNode<T> RightChild {get;set;}
    public T Value { get; set;}
}

Вы также должны изменить поле current на это:

private AvlTreeNode<T> current = new AvlTreeNode<T>();
2 голосов
/ 15 мая 2010

Не могли бы вы попробовать изменить его на

class AvlTreePreOrderEnumerator<T> : IEnumerator<T> where T :IComparable

1 голос
/ 15 мая 2010

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

1 голос
/ 15 мая 2010

Хотя вы еще не опубликовали фактический код, вызывающий ошибку (Opdr2_AvlTreeTest_Final.AvlTreeNode), я сильно подозреваю, что проблема заключается в том, что вы используете этот класс в универсальном методе / типе с параметром типа, который не ограничен для реализации IComparable<T>.

Вы можете воспроизвести похожую ошибку на простом примере:

// no problem here at definition site:
void IsLarger<T>(T a, T b) where T : IComparable<T> {
   return a.CompareTo(b) > 0;
}

void Test<T>(T arg) { // note: T is not necessarily IComparable<T>
   Console.WriteLine(IsLarger(arg, arg)); // The compiler shouldn't allow this.
}
...