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).
Dictionary<string, Dictionary<string, Dictionary<string, [...]>>>
We can use generics while defining our builders to tell Java that return type of methods is not the builder's class but rather the subclass of the builder, hence recursive generic definition.
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
Generic Classes These classes are known as parameterized classes or parameterized types because they accept one or more parameters.
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.
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> { }
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With