2009-03-15 18 views
15

¿Es posible definir un tipo genérico en C# que se refiera a sí mismo?Tipos genéricos recursivos

E.g. Quiero definir un Dictionary <> que tenga su tipo como TValue (para una jerarquía).

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

No, esto no es posible. ¿Podría ser más específico en lo que está tratando de lograr? –

+0

lol Earwicker, tienes que aceptar que es raro;) ... También pensé que no (directamente) ... – eglasius

+0

Creo que la gente se confunde porque una clase no puede heredarse de sí misma (obviamente, o tendría un tamaño infinito como pronto como tenía cualquier campo), ni un genérico puede heredar de un parámetro de tipo, pero el nombre propio de la clase y los parámetros de tipo pueden aparecer en los argumentos de tipo de una base genérica muy bien. –

Respuesta

41

Probar:

class StringToDictionary : Dictionary<string, StringToDictionary> { } 

entonces usted puede escribir:

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

Principio general de la recursividad: encontrar la manera de dar un nombre al patrón recurrente, por lo que puede referirse a sí mismo por nombre.

+0

+1 muy agradable, que en realidad compila/ejecuta – eglasius

+0

gracias! bueno, ese diccionario no está sellado :) – laktak

+4

cálculo lambda para la victoria! – data

7

Otro ejemplo sería el árbol genérico

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

Ahora utilizarlo

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 
} 

Tenga en cuenta que no se puede crear una instancia directamente Tree<T>. Tiene que ser una clase base para la clase de nodo en el árbol. Piense en class Node : Tree<Node> { }.

Cuestiones relacionadas