首页 > 解决方案 > 获取 Tree 中的所有孩子

问题描述

有一个类存储元素树。子元素存储在

public List<BaseTreeData> Child { get; set; }

我想将此树显示为所有元素的“平面”(线性)列表。将类分为两个(基类和继承类)后,GetChildren方法会生成关于类型不匹配的错误。很可能一切都是合乎逻辑的,但是如何解决呢?

错误 CS1503 参数 1:无法从“ConsoleApplication1.BaseTreeData”转换为“ConsoleApplication1.TreeData”

namespace ConsoleApplication1
{
    class Program
    {        
        static void Main(string[] args)
        {
            var data = new List<TreeData>();
            for (int i = 0; i < 5; i++)
            {
                var item = new TreeData() { Name = i.ToString() };
                for (int j = 0; j < 3; j++)
                {
                    var number = (i + 1) * 10 + j;
                    item.Child.Add(new TreeData() { ID = number, Name = number.ToString(), Parent = item });                    
                }
                data.Add(item);
            }

            foreach (var item in data.SelectMany(x => GetChildren(x)))
            {
                Console.WriteLine(item.ID + " " + item.Name + " " + item.IsChecked);
            }
        }

        static IEnumerable<TreeData> GetChildren(TreeData d)
        {
            return new[] { d }.Concat(d.Child).SelectMany(x => GetChildren(x));
        }
    }

    class BaseTreeData
    {
        public bool IsChecked { get; set; }
        public BaseTreeData Parent { get; set; }
        public List<BaseTreeData> Child { get; set; }

        public BaseTreeData()
        {
            Child = new List<BaseTreeData>();
        }
    }

    class TreeData : BaseTreeData
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

标签: c#

解决方案


错误 CS1503 参数 1:无法从“ConsoleApplication1.BaseTreeData”转换为“ConsoleApplication1.TreeData”

发生此错误是因为子节点BaseTreeData不是TreeData.

使用BaseTreeData您发布的类定义,child并将parent始终返回基类型。

相反,您可以使用泛型解决此问题,以便子节点与父类具有相同的类型:

class BaseTreeData<T> where T : BaseTreeData<T>
{
    public bool IsChecked { get; set; }
    public T Parent { get; set; }
    public List<T> Children { get; set; }

    public BaseTreeData()
    {
        Children = new List<T>();
    }

    public IEnumerable<T> GetAncestors()
    {
        if (Parent == null)
            yield break;

        T relative = Parent;
        while (relative != null)
        {
            yield return relative;
            relative = relative.Parent;
        }
    }

    public IEnumerable<T> GetDescendants()
    {
        var nodes = new Stack<T>();
        nodes.Push(this as T);

        while (nodes.Any())
        {
            var current = nodes.Pop();
            yield return current;

            foreach (var childNode in current.Children)
                nodes.Push(childNode);
        }
    }
}

class TreeData : BaseTreeData<TreeData>
{
    public int ID { get; set; }
    public string Name { get; set; }
}

推荐阅读