2009-03-15 14 views
15

Ist es möglich, einen generischen Typ in C# zu definieren, der auf sich selbst verweist?Rekursive generische Typen

z. Ich möchte ein Dictionary <> definieren, das seinen Typ als TValue (für eine Hierarchie) enthält.

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

Nein, das ist nicht möglich. Könnten Sie genauer beschreiben, was Sie erreichen möchten? –

+0

lol Earwicker, du musst zustimmen es ist komisch;) ... Ich dachte auch, dass es nicht (direkt) .. – eglasius

+0

Ich denke, die Leute werden verwirrt, weil eine Klasse nicht von sich selbst erben kann (offensichtlich, oder es hätte unendliche Größe als bald, da es irgendwelche Felder hatte), noch kann eine generische von einem Typparameter erben, aber die eigenen Namen- und Typparameter der Klasse können in den Typargumenten einer generischen Basis gerade fein erscheinen. –

Antwort

41

Versuchen:

class StringToDictionary : Dictionary<string, StringToDictionary> { } 

Dann können Sie schreiben:

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

Allgemeines Prinzip für Rekursion: einen Weg finden, einen Namen für das rekursive Muster zu geben, so dass es verweisen sich selbst mit Namen.

+0

+1 sehr nett, das kompiliert/läuft – eglasius

+0

danke! gut, dass Wörterbuch nicht versiegelt ist :) – laktak

+4

Lambda-Kalkül für den Sieg! – data

7

Ein weiteres Beispiel Nun generic Baum wäre

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; } } 
} 

es

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 
} 

Hinweis zu verwenden, die Sie nicht direkt Tree<T> instanziieren. Es muss eine Basisklasse für die Knotenklasse in der Struktur sein. Denken Sie class Node : Tree<Node> { }.

Verwandte Themen