Рекурсивные универсальные типы - PullRequest
18 голосов
/ 15 марта 2009

Можно ли определить универсальный тип в C #, который ссылается на себя?

например. Я хочу определить словарь <>, который содержит его тип как TValue (для иерархии).

Dictionary<string, Dictionary<string, Dictionary<string, [...]>>>

Ответы [ 2 ]

48 голосов
/ 15 марта 2009

Попробуйте:

class StringToDictionary : Dictionary<string, StringToDictionary> { }

Тогда вы можете написать:

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

Общий принцип рекурсии: найдите способ дать имя рекурсивному шаблону, чтобы он мог ссылаться на себя по имени.

11 голосов
/ 06 августа 2014

Другим примером будет родовое дерево

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

Теперь, чтобы использовать его

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
}

Обратите внимание, что вы не можете напрямую создать экземпляр Tree<T>. Это должен быть базовый класс для класса узла в дереве. Подумайте class Node : Tree<Node> { }.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...