Recursive generic types

前端 未结 2 1333
悲&欢浪女
悲&欢浪女 2020-11-29 06:27

Is it possible to define a generic type in C# that references itself?

E.g. I want to define a Dictionary<> that holds its type as TValue (for a hierarchy).

<
相关标签:
2条回答
  • 2020-11-29 07:21

    Try:

    class StringToDictionary : Dictionary<string, StringToDictionary> { }
    

    Then you can write:

    var stuff = new StringToDictionary
            {
                { "Fruit", new StringToDictionary
                    {
                        { "Apple", null },
                        { "Banana", null },
                        { "Lemon", new StringToDictionary { { "Sharp", null } } }
                    }
                },
            };
    

    General principle for recursion: find some way to give a name to the recursive pattern, so it can refer to itself by name.

    0 讨论(0)
  • 2020-11-29 07:22

    Another example would be generic tree

    public class Tree<TDerived> where TDerived : Tree<TDerived>
    {
        public TDerived Parent { get; private set; }
        public List<TDerived> Children { get; private set; }
        public Tree(TDerived parent)
        {
            this.Parent = parent;
            this.Children = new List<TDerived>();
            if(parent!=null) { parent.Children.Add(this); }
        }
        public bool IsRoot { get { return Parent == null; } }
        public bool IsLeaf { get { return Children.Count==0; } }
    }
    

    Now to use it

    public class CoordSys : Tree<CoordSys>
    {
        CoordSys() : base(null) { }
        CoordSys(CoordSys parent) : base(parent) { }
        public double LocalPosition { get; set; }
        public double GlobalPosition { get { return IsRoot?LocalPosition:Parent.GlobalPosition+LocalPosition; } }
        public static CoordSys NewRootCoordinate() { return new CoordSys(); }
        public CoordSys NewChildCoordinate(double localPos)
        {
            return new CoordSys(this) { LocalPosition = localPos };
        }
    }
    
    static void Main() 
    {
        // Make a coordinate tree:
        //
        //                  +--[C:50] 
        // [A:0]---[B:100]--+         
        //                  +--[D:80] 
        //
    
        var A=CoordSys.NewRootCoordinate();
        var B=A.NewChildCoordinate(100);
        var C=B.NewChildCoordinate(50);
        var D=B.NewChildCoordinate(80);
    
        Debug.WriteLine(C.GlobalPosition); // 100+50 = 150
        Debug.WriteLine(D.GlobalPosition); // 100+80 = 180
    }
    

    Note that you cannot directly instantiate Tree<TDerived>. It has to be a base class to the node class in the tree. Think class Node : Tree<Node> { }.

    0 讨论(0)
提交回复
热议问题