为通用树 C#​​ 实现 IEnumerable

Implementing IEnumerable for generic tree c#

我有一个通用树 class,我想为其实现 IEnumerable 接口。之前在Whosebug上查到的问题跟我的问题有点不一样。我知道我在绞尽脑汁,但我不知道那是什么。这是我的代码:

class Node<T>: IEnumerable<T>
{
    private T data;
    private LinkedList<Node<T>> children;

    public Node(T data)
    {
        this.data = data;
        children = new LinkedList<Node<T>>();
    }

    public void AddChildNode(Node<T> node)
    {
        children.AddFirst(node);
    }

    public void MyTraverse(Node<T> node, List<T> visited)
    {
        visited.Add(node.data);
        foreach (Node<T> kid in node.children)
            MyTraverse(kid, visited);

    }

    public IEnumerator<T> GetEnumerator()
    {
        return children.GetEnumerator();
    }


    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

在函数 GetEnumerator() 中,我遇到了一个我不知道如何修复的转换错误。谁能帮帮我?

您可能想要 IEnumerable<Node<T>> 接口实现(您正在枚举 nodes Node<T>,而不是 T 实例)而不仅仅是 IEnumerable<T>一个:

 class Node<T>: IEnumerable<Node<T>> {
   ...
    public IEnumerator<Node<T>> GetEnumerator() {
      return children.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
      return GetEnumerator();
    }
 }

问题是children是这样定义的:

private LinkedList<Node<T>> children;

这意味着 childrenIEnumerable<Node<T>>,而不是 IEnumerable<T>

因为你想要它作为 IEnumerable<T> 你必须提取 data 成员。根据你的遍历方法是如何定义的,我还怀疑你希望它递归地下降到节点 children:

public IEnumerator<T> GetEnumerator()
{
    yield return data;
    foreach (var childNode in children)
        foreach (var child in childNode)
            yield return child;
}

如果您只想将其 return children,请使用此代码:

public IEnumerator<T> GetEnumerator()
{
    return children.Select(node => node.data);
}

获取枚举器就像::

 public IEnumerator<Node<T>> GetEnumerator()
    {
        return children.GetEnumerator();
    }
public class Node : IEnumerable<Node>
{
    public string Name { get; internal set; }
    public string Value { get; internal set; }

    public Node Parent { get; internal set; }
    public List<Node> Children { get; internal set; }

    public Node(string name)
    {
        if (string.IsNullOrEmpty(name))
            throw new ArgumentException($"{nameof(Name)}");

        Name = name;
        Children = new List<Node>();
    }

    IEnumerator IEnumerable.GetEnumerator()
        => GetEnumerator();

    public IEnumerator<Node> GetEnumerator()
    {
        var self = this;
        var queue = new Queue<Node>();
        queue.Enqueue(self);

        while (queue.Any())
        {
            yield return queue.Dequeue();
            foreach (var child in self.Children)
                queue.Enqueue(child);
        }
    }             
}

此外,这也是可行的,而且代码更少:

     public IEnumerator<Node> GetEnumerator()
    {
        var self = this;
        yield return self;

        foreach (var child in self.Children)
            yield return child;
    }