The code below is a short "summary" of my real project that contain only the relevant parts to understand my question. (and don`t want to ruin someones day with the original code).
imagine you have 4 classes: Division, Branch, Department and Team. every class inherits base class in that order.
The final goal: return one division object that holds List of 7 Branches, each Branch holds List of 7 Departments and each Department holds List of 7 Teams.
for example i will be able to reach from outside to every class instance:
division d = new division();
d.CreateDivisionStructure();
int Example = d.ListOfBranches[5].ListOfDepartments[4].ListOfTeam[3].SomeIntegerProperty;
(the original code has that lists, override functions, properties etc..)
the problem: imagine that protected string _myVar in the code below is a Datatable that needs to initialized via myVarproperty with heavy resource consuming SQL query. hence, my wish is to initialize protected string _myVar only one time for all the creation of the "division units structure". in the code below protected string _myVar will be null 64 times and will be initialized 64 times (for my understanding 7 times for each unit and one time for each base() call).
how can i achieve that?
i tried quite a lot other ways but could not solve that. I would appreciate any help, different way of thinking or advice.
class Program
{
static void Main(string[] args)
{
division d = new division();
d.CreateDivisionStructure();
Console.ReadLine();
}
}
class division
{
private static int CountHowManyTimesMyVarWasInitilized = 0;
public division()
{
}
protected string _myVar;
public string myVar
{
get
{
if (_myVar == null)
{
CountHowManyTimesMyVarWasInitilized++;
Console.WriteLine(CountHowManyTimesMyVarWasInitilized);
_myVar = "now myVar is not null";
return _myVar;
}
else
{ return _myVar; }
}
set { _myVar = value; }
}
public void CreateDivisionStructure()
{
Console.WriteLine(myVar);
for (int i = 0; i < 7; i++)
{
Branch b = new Branch(7);
}
}
}
class Branch : division
{
public Branch(bool dImDerivedClass)
{
// constructor for department to prevent recursive stackoverflow if base of department will call the empty constructor
}
public Branch(int NumberOfBranches)
{
Console.WriteLine(myVar);
Department d = new Department(7);
}
}
class Department : Branch
{
public Department(bool ImDerivedClass) : base(true)
{
// constructor for team to prevent recursive stackoverflow if base of Team will call the empty constructor
}
public Department(int numberOfDep) : base(true)
{
for (int i = 0; i < numberOfDep; i++)
{
Console.WriteLine(myVar);
Team t = new Team(7);
}
}
}
class Team : Department
{
public Team(int numberOfTeams) : base(true)
{
for (int i = 0; i < numberOfTeams; i++)
{
Console.WriteLine(myVar);
}
}
}
}
This is likely a good use of the Lazy<T> class, used in a static variable so there is only a single copy for the process. It will run the Func you give it once to initialize during the first access of the variable.
https://msdn.microsoft.com/en-us/library/dd642331(v=vs.110).aspx
However, based on your class structure I'm not sure if it is the best approach. What is the purpose for the hierarchy of Branch : division and Department : Branch. Is the Branch a Division? If you are trying to share common properties as to not code them over again, I would suggest creating a common class that can hold those variables that Branch, Division, and Department can inherit from.
You can use a static variable / static constructor in the lowest class in the hierarchy. The static constructor will only be called once.
A simple solution is to use a "control" variable.
I'm sure you can improve your design and avoid this problem but I don't have time to check it now..
using System;
namespace Program
{
internal class Program
{
private static void Main(string[] args)
{
division d = new division();
d.CreateDivisionStructure();
Console.ReadLine();
}
}
internal class division
{
private static int CountHowManyTimesMyVarWasInitilized = 0;
public division()
{
}
protected string _myVar;
private bool _isReadyForInitialization;
public string myVar
{
get
{
if (!_isReadyForInitialization)
return null;
if (_myVar == null)
{
CountHowManyTimesMyVarWasInitilized++;
Console.WriteLine(CountHowManyTimesMyVarWasInitilized);
_myVar = "now myVar is not null";
return _myVar;
}
else
{ return _myVar; }
}
set { _myVar = value; }
}
public void CreateDivisionStructure()
{
// now _myVar is spposed to be initilized to all dirved clasess isnt is?
Console.WriteLine(myVar);
for (int i = 0; i < 7; i++)
{
Branch b = new Branch(7);
}
_isReadyForInitialization = true;
Console.WriteLine(myVar);
}
}
internal class Branch : division
{
public Branch(bool dImDerivedClass)
{
// constructor for department to prevent recursive stackoverflow if base of department will call the empty constructor
}
public Branch(int NumberOfBranches)
{
Console.WriteLine(myVar);
Department d = new Department(7);
}
}
internal class Department : Branch
{
public Department(bool ImDerivedClass) : base(true)
{
// constructor for team to prevent recursive stackoverflow if base of Team will call the empty constructor
}
public Department(int numberOfDep) : base(true)
{
for (int i = 0; i < numberOfDep; i++)
{
Console.WriteLine(myVar);
Team t = new Team(7);
}
}
}
internal class Team : Department
{
public Team():base(false)
{
}
public Team(int numberOfTeams) : base(true)
{
for (int i = 0; i < numberOfTeams; i++)
{
Console.WriteLine(myVar);
}
}
}
}
I have a few classes which have some primitive fields and I would like to create a generalized wrapper for them in order to access their fields. This wrapper should somehow contain a reference to the fields of my classes so that I can read/write the values of these fields. The idea is to create a genralized architecture for these classes so that I dont have to write code for each of them. The classes have fields which have a number in them which will be used as an Id to access the fields.
This is some example code that might shed some light on my requirement. What I want in the end is to change the value of some field in the object of Fancy1 class without accessing the object itself but through its wrapper.
class Fancy1
{
public double level1;
public bool isEnable1;
public double level2;
public bool isEnable2;
public double level3;
}
class Fancy2
{
public double level4;
public bool isEnable4;
public double level6;
public bool isEnable6;
public double level7;
}
class FieldWrapper
{
public int id { get; set; }
public object level { get; set; }
public object isEnabled { get; set; }
public FieldWrapper(int id, object level, object isEnabled)
{
this.id = id;
this.level = level;
this.isEnabled = isEnabled;
}
}
class FancyWrapper
{
private Fancy scn;
public FancyWrapper(Fancy scn)
{
if (!(scn is Fancy))
throw new ArgumentException(scn.GetType().FullName + " is not a supported type!");
this.scn = scn;
}
private Dictionary<int, FieldWrapper> fieldLut = new Dictionary<int, FieldWrapper>();
private List<FieldWrapper> _fields { get { return fieldLut.Values.ToList(); } }
public List<FieldWrapper> fields
{
get
{
if (_fields.Count == 0)
{
foreach (System.Reflection.FieldInfo fieldInfo in scn.GetType().GetFields())
{
if (fieldInfo.FieldType == typeof(double))
{
int satId = getIdNr(fieldInfo.Name);
fieldLut.Add(satId, new FieldWrapper(satId, fieldInfo.GetValue(scn), true));
}
}
foreach (System.Reflection.FieldInfo fieldInfo in scn.GetType().GetFields())
{
if (fieldInfo.FieldType == typeof(bool))
{
int satId = getIdNr(fieldInfo.Name);
fieldLut[satId].isEnabled = fieldInfo.GetValue(scn);
}
}
}
return _fields;
}
}
private int getIdNr(string name)
{
System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(name, #"\d+");
return Int32.Parse(m.Value);
}
}
class Program
{
static void Main(string[] args)
{
Fancy1 fancy = new Fancy1();
fancy.level1 = 1;
fancy.isEnable1 = true;
fancy.level2 = 2;
fancy.isEnable2 = false;
fancy.level3 = 3;
FancyWrapper wrapper = new FancyWrapper(fancy);
wrapper.fields[2].level = 10;
// fancy.level2 should somehow get the value I set via the wrapper
Console.WriteLine(fancy.level2);
Console.ReadLine();
}
}
EDIT: Fancy classes cannot be changed since they are part of an interface!
Depending on how many Fancy classes you are dealing with, you could create an adapter/facade class for each the expose a common interface. eg:
class Fancy1
{
public double level1;
public bool isEnable1;
public double level2;
public bool isEnable2;
public double level3;
}
public class FieldWrapper
{
private Action<double> _levelSetter;
private Func<double> _levelGetter;
private Action<bool> _enableSetter;
private Func<bool> _enableGetter;
public double level { get { return _levelGetter(); } set { _levelSetter(value); }}
public bool isEnabled { get { return _enableGetter(); } set { _enableSetter(value); }}
internal FieldWrapper(Func<double> levelGetter, Action<double> levelSetter, Func<bool> enableGetter, Action<bool> enableSetter)
{
_levelGetter = levelGetter;
_levelSetter = levelSetter;
_enableGetter = enableGetter;
_enableSetter = enableSetter;
}
}
abstract class FancyWrapper
{
public FieldWrapper[] Fields { get; protected set; }
}
class Fancy1Wrapper : FancyWrapper
{
private Fancy1 _fancy1;
public Fancy1Wrapper(Fancy1 fancy1)
{
_fancy1 = fancy1;
this.Fields = new[] { new FieldWrapper(() => fancy1.level1, level => _fancy1.level1 = level, () => _fancy1.isEnable1, enable => _fancy1.isEnable1 = enable),
new FieldWrapper(() => fancy1.level2, level => _fancy1.level2 = level, () => _fancy1.isEnable2, enable => _fancy1.isEnable2 = enable), };
}
}
Or you could invest 5 minutes learning data structures. Consider following example:
var levels = new Dictionary<int, bool>
{
{1, true},
{2, false}
};
if (levels[1])
{
//will run, because level 1 is true
}
if (levels[2])
{
//will not run, because level 2 is false
}
if (levels.ContainsKey(3) && levels[3])
{
//will not run, because dictionary does not contain entry for key 3
}
levels.Add(3, false);
if (levels.ContainsKey(3) && levels[3])
{
//will not run, because level 3 is false
}
levels[3] = true;
if (levels.ContainsKey(3) && levels[3])
{
//will run, because level 3 is true
}
That may seem like what you want, but it really isn't. It is extremely awkward on any number of levels. More specifically, pointers are generally rather "Un-C#-like" and having to know about these numbers defeats the point of having separate classes to begin with.
Think closely about what you want to accomplish. If you're having problems translating it into code, we're here to help. :)
interface IFly<T>
{
T GetMark();
}
public class Bird : IFly<string>
{
public string GetMark()
{
return "Bird";
}
}
public class Plane : IFly<int>
{
public int GetMark()
{
return 123;
}
}
class Program
{
static void Main()
{
IFly<string> bird = new Bird();
IFly<int> plane = new Plane();
Console.WriteLine(bird.GetMark());
Console.WriteLine(plane.GetMark());
Console.ReadKey();
}
}
I would like to replace this
IFly<string> bird = new Bird();
IFly<int> plane = new Plane();
with something like this:
var fly = new List<IFly<T>>
Any suggestions?
This might work:
public interface IFlyRoot { }
interface IFly<T> : IFlyRoot
{
T GetMark();
}
Then you can make a List<IFlyRoot>.
In general case #Steve's answer is the right one. However, depending on your needs you could try using type variance, but it doesn't support value types (int wouldn't work).
Notice the out in interface definition:
interface IFly<out T>
{
T GetMark();
}
Then you are allowed to write:
var list = new List<IFly<object>>();
list.Add(bird);
but it won't work with Plane, where T is a value type (here: int). This solution may not suit your exact needs then.
To get more insight into why variance doesn't work with value types refer to answers of Jon Skeet or Eric Lippert. In short, it's because reference identity should be preserved, but with value types it cannot. A value type would always be boxed first, loosing that identity. That's why it doesn't work automatically. There's not really a clean way around this. One thing you could try is to make Plane class explicitly implement IFly<object> as well:
public class Plane : IFly<int>, IFly<object>
{
public int GetMark()
{
return 123;
}
object IFly<object>.GetMark()
{
return GetMark();
}
}
And add to list:
list.Add(new Plane());
Since IFly and IFly are considered different types by the CLR you will need to establish a more direct relationship between the two, in this case by implementing a non-generic version of the interface IFly. The collection would then store objects as long as they implement this common interface for example:
class Program
{
static void Main()
{
var flyingThings = new ThingsThatFlyCollection();
var bird = new Bird();
var bird2 = new Bird();
var plane = new Plane();
flyingThings.Add(bird);
flyingThings.Add(bird2);
flyingThings.Add(plane);
Console.WriteLine(flyingThings.GetItemWithCast<string>(0).GetMark());
Console.WriteLine(flyingThings.GetItemWithCast<string>(1).GetMark());
Console.WriteLine(flyingThings.GetItemWithCast<int>(2).GetMark());
foreach (var item in flyingThings.GetItemsWithCast<int>())
{
Console.WriteLine(item.GetMark());
}
foreach (var item in flyingThings.GetItemsWithCast<string>())
{
Console.WriteLine(item.GetMark());
}
foreach (var item in flyingThings.GetItemsByType<Bird>())
{
Console.WriteLine(item.GetMark());
}
Console.ReadKey();
}
}
public interface IFly
{
object GetMark();
}
public interface IFly<TMark> : IFly
{
new TMark GetMark();
}
class Plane : IFly<int>
{
public int GetMark() { return 123; }
object IFly.GetMark() { return this.GetMark(); }
}
class Bird : IFly<string>
{
public string GetMark() { return "Bird"; }
object IFly.GetMark() { return this.GetMark(); }
}
class ThingsThatFlyCollection : Collection<IFly>
{
public IFly<TMark> GetItemWithCast<TMark>(int index)
{
var f = this[index] as IFly<TMark>;
if (f == null) { throw new InvalidCastException(); }
return f;
}
public IEnumerable<IFly<TMark>> GetItemsWithCast<TMark>()
{
var items = this.Where(p => p is IFly<TMark>).Cast<IFly<TMark>>();
return items;
}
public IEnumerable<TFlyer> GetItemsByType<TFlyer>() where TFlyer : IFly
{
var items = this.Where(p => p.GetType() == typeof(TFlyer)).Cast<TFlyer>();
return items;
}
}
Keep in mind that upcasting can have some performance implications depending on transaction volume, however is probably negligible for most scenarios.
I have a custom class defined:
class Car
{
public string a;
public string b;
public string c;
public static void GetCar()
{
var car = new Car[4];
for(int i=0; i<4; ++i)
{
novica[i]= new Novica();
novica[i].a="abc";
novica[i].b="abc";
novica[i].c="abc";
}
}
}
This fills the array with values, and now I would like to use this array with the values it gets (loading string from HTML) in a function that is not part of this class. Is it possible and if so, how?
In order to use it elsewhere, you would need to return the array from your function, like so:
public static Car[] GetCar()
{
var car = new Car[4];
for(int i=0; i<4; ++i)
{
car[i]= new Novica();
car[i].a="abc";
car[i].b="abc";
car[i].c="abc";
}
return car;
}
You can't. Your method doesn't actually return anything.
If you were to change the method signature to return the array the method creates:
public static Car[] GetCar()
{
// Body
return car;
}
The call would become as simple as:
var cars = Car.GetCar();
I suggest a slightly different construction. Provide an array containing all cars as static property
public class Car
{
public static Car[] AllCars { get; private set; }
public Car()
{
// Class and constructor somewhat simplyfied.
AllCars = new Car[4];
for (int i = 0; i < 4; ++i) {
AllCars[i] = new Novica();
}
}
}
Now you can work with cars like this
foreach (Car car in Car.AllCars) {
// do something with car
}
Or access a specific car with
string a = Car.AllCars[i].a;
I was looking for a tree or graph data structure in C#, but I guess there isn't one provided. An Extensive Examination of Data Structures Using C# 2.0 a bit about why. Is there a convenient library which is commonly used to provide this functionality? Perhaps through a strategy pattern to solve the issues presented in the article.
I feel a bit silly implementing my own tree, just as I would implementing my own ArrayList.
I just want a generic tree which can be unbalanced. Think of a directory tree. C5 looks nifty, but their tree structures seem to be implemented as balanced red-black trees better suited to search than representing a hierarchy of nodes.
My best advice would be that there is no standard tree data structure because there are so many ways you could implement it that it would be impossible to cover all bases with one solution. The more specific a solution, the less likely it is applicable to any given problem. I even get annoyed with LinkedList - what if I want a circular linked list?
The basic structure you'll need to implement will be a collection of nodes, and here are some options to get you started. Let's assume that the class Node is the base class of the entire solution.
If you need to only navigate down the tree, then a Node class needs a List of children.
If you need to navigate up the tree, then the Node class needs a link to its parent node.
Build an AddChild method that takes care of all the minutia of these two points and any other business logic that must be implemented (child limits, sorting the children, etc.)
delegate void TreeVisitor<T>(T nodeData);
class NTree<T>
{
private T data;
private LinkedList<NTree<T>> children;
public NTree(T data)
{
this.data = data;
children = new LinkedList<NTree<T>>();
}
public void AddChild(T data)
{
children.AddFirst(new NTree<T>(data));
}
public NTree<T> GetChild(int i)
{
foreach (NTree<T> n in children)
if (--i == 0)
return n;
return null;
}
public void Traverse(NTree<T> node, TreeVisitor<T> visitor)
{
visitor(node.data);
foreach (NTree<T> kid in node.children)
Traverse(kid, visitor);
}
}
Simple recursive implementation...
< 40 lines of code...
You just need to keep a reference to the root of the tree outside of the class,
or wrap it in another class, maybe rename to TreeNode??
Here's mine, which is very similar to Aaron Gage's, just a little more conventional, in my opinion. For my purposes, I haven't ran into any performance issues with List<T>. It would be easy enough to switch to a LinkedList if needed.
namespace Overby.Collections
{
public class TreeNode<T>
{
private readonly T _value;
private readonly List<TreeNode<T>> _children = new List<TreeNode<T>>();
public TreeNode(T value)
{
_value = value;
}
public TreeNode<T> this[int i]
{
get { return _children[i]; }
}
public TreeNode<T> Parent { get; private set; }
public T Value { get { return _value; } }
public ReadOnlyCollection<TreeNode<T>> Children
{
get { return _children.AsReadOnly(); }
}
public TreeNode<T> AddChild(T value)
{
var node = new TreeNode<T>(value) {Parent = this};
_children.Add(node);
return node;
}
public TreeNode<T>[] AddChildren(params T[] values)
{
return values.Select(AddChild).ToArray();
}
public bool RemoveChild(TreeNode<T> node)
{
return _children.Remove(node);
}
public void Traverse(Action<T> action)
{
action(Value);
foreach (var child in _children)
child.Traverse(action);
}
public IEnumerable<T> Flatten()
{
return new[] {Value}.Concat(_children.SelectMany(x => x.Flatten()));
}
}
}
Yet another tree structure:
public class TreeNode<T> : IEnumerable<TreeNode<T>>
{
public T Data { get; set; }
public TreeNode<T> Parent { get; set; }
public ICollection<TreeNode<T>> Children { get; set; }
public TreeNode(T data)
{
this.Data = data;
this.Children = new LinkedList<TreeNode<T>>();
}
public TreeNode<T> AddChild(T child)
{
TreeNode<T> childNode = new TreeNode<T>(child) { Parent = this };
this.Children.Add(childNode);
return childNode;
}
... // for iterator details see below link
}
Sample usage:
TreeNode<string> root = new TreeNode<string>("root");
{
TreeNode<string> node0 = root.AddChild("node0");
TreeNode<string> node1 = root.AddChild("node1");
TreeNode<string> node2 = root.AddChild("node2");
{
TreeNode<string> node20 = node2.AddChild(null);
TreeNode<string> node21 = node2.AddChild("node21");
{
TreeNode<string> node210 = node21.AddChild("node210");
TreeNode<string> node211 = node21.AddChild("node211");
}
}
TreeNode<string> node3 = root.AddChild("node3");
{
TreeNode<string> node30 = node3.AddChild("node30");
}
}
BONUS
See fully-fledged tree with:
iterator
searching
Java/C#
https://github.com/gt4dev/yet-another-tree-structure
The generally excellent C5 Generic Collection Library has several different tree-based data structures, including sets, bags and dictionaries. Source code is available if you want to study their implementation details. (I have used C5 collections in production code with good results, although I haven't used any of the tree structures specifically.)
See https://github.com/YaccConstructor/QuickGraph (previously http://quickgraph.codeplex.com/)
QuickGraph provides generic directed/undirected graph data structures and algorithms for .NET 2.0 and up. QuickGraph comes with algorithms such as depth-first search, breadth-first search, A* search, shortest path, k-shortest path, maximum flow, minimum spanning tree, least common ancestors, etc... QuickGraph supports MSAGL, GLEE, and Graphviz to render the graphs, serialization to GraphML, etc.
Here's my own:
class Program
{
static void Main(string[] args)
{
var tree = new Tree<string>()
.Begin("Fastfood")
.Begin("Pizza")
.Add("Margherita")
.Add("Marinara")
.End()
.Begin("Burger")
.Add("Cheese burger")
.Add("Chili burger")
.Add("Rice burger")
.End()
.End();
tree.Nodes.ForEach(p => PrintNode(p, 0));
Console.ReadKey();
}
static void PrintNode<T>(TreeNode<T> node, int level)
{
Console.WriteLine("{0}{1}", new string(' ', level * 3), node.Value);
level++;
node.Children.ForEach(p => PrintNode(p, level));
}
}
public class Tree<T>
{
private Stack<TreeNode<T>> m_Stack = new Stack<TreeNode<T>>();
public List<TreeNode<T>> Nodes { get; } = new List<TreeNode<T>>();
public Tree<T> Begin(T val)
{
if (m_Stack.Count == 0)
{
var node = new TreeNode<T>(val, null);
Nodes.Add(node);
m_Stack.Push(node);
}
else
{
var node = m_Stack.Peek().Add(val);
m_Stack.Push(node);
}
return this;
}
public Tree<T> Add(T val)
{
m_Stack.Peek().Add(val);
return this;
}
public Tree<T> End()
{
m_Stack.Pop();
return this;
}
}
public class TreeNode<T>
{
public T Value { get; }
public TreeNode<T> Parent { get; }
public List<TreeNode<T>> Children { get; }
public TreeNode(T val, TreeNode<T> parent)
{
Value = val;
Parent = parent;
Children = new List<TreeNode<T>>();
}
public TreeNode<T> Add(T val)
{
var node = new TreeNode<T>(val, this);
Children.Add(node);
return node;
}
}
Output:
Fastfood
Pizza
Margherita
Marinara
Burger
Cheese burger
Chili burger
Rice burger
I have a little extension to the solutions.
Using a recursive generic declaration and a deriving subclass, you can better concentrate on your actual target.
Notice, it’s different from a non generic implementation, you don’t need to cast 'node' to 'NodeWorker'.
Here's my example:
public class GenericTree<T> where T : GenericTree<T> // recursive constraint
{
// no specific data declaration
protected List<T> children;
public GenericTree()
{
this.children = new List<T>();
}
public virtual void AddChild(T newChild)
{
this.children.Add(newChild);
}
public void Traverse(Action<int, T> visitor)
{
this.traverse(0, visitor);
}
protected virtual void traverse(int depth, Action<int, T> visitor)
{
visitor(depth, (T)this);
foreach (T child in this.children)
child.traverse(depth + 1, visitor);
}
}
public class GenericTreeNext : GenericTree<GenericTreeNext> // concrete derivation
{
public string Name {get; set;} // user-data example
public GenericTreeNext(string name)
{
this.Name = name;
}
}
static void Main(string[] args)
{
GenericTreeNext tree = new GenericTreeNext("Main-Harry");
tree.AddChild(new GenericTreeNext("Main-Sub-Willy"));
GenericTreeNext inter = new GenericTreeNext("Main-Inter-Willy");
inter.AddChild(new GenericTreeNext("Inter-Sub-Tom"));
inter.AddChild(new GenericTreeNext("Inter-Sub-Magda"));
tree.AddChild(inter);
tree.AddChild(new GenericTreeNext("Main-Sub-Chantal"));
tree.Traverse(NodeWorker);
}
static void NodeWorker(int depth, GenericTreeNext node)
{ // a little one-line string-concatenation (n-times)
Console.WriteLine("{0}{1}: {2}", String.Join(" ", new string[depth + 1]), depth, node.Name);
}
Try this simple sample.
public class TreeNode<TValue>
{
#region Properties
public TValue Value { get; set; }
public List<TreeNode<TValue>> Children { get; private set; }
public bool HasChild { get { return Children.Any(); } }
#endregion
#region Constructor
public TreeNode()
{
this.Children = new List<TreeNode<TValue>>();
}
public TreeNode(TValue value)
: this()
{
this.Value = value;
}
#endregion
#region Methods
public void AddChild(TreeNode<TValue> treeNode)
{
Children.Add(treeNode);
}
public void AddChild(TValue value)
{
var treeNode = new TreeNode<TValue>(value);
AddChild(treeNode);
}
#endregion
}
I created a Node<T> class that could be helpful for other people. The class has properties like:
Children
Ancestors
Descendants
Siblings
Level of the node
Parent
Root
Etc.
There is also the possibility to convert a flat list of items with an Id and a ParentId to a tree. The nodes holds a reference to both the children and the parent, so that makes iterating nodes quite fast.
There is the now released .NET codebase: specifically the code for a SortedSet that implements a red-black tree: sortedset.cs
This is, however, a balanced tree structure. So my answer is more a reference to what I believe is the only native tree-structure in the .NET core library.
I've completed the code that Berezh has shared.
public class TreeNode<T> : IEnumerable<TreeNode<T>>
{
public T Data { get; set; }
public TreeNode<T> Parent { get; set; }
public ICollection<TreeNode<T>> Children { get; set; }
public TreeNode(T data)
{
this.Data = data;
this.Children = new LinkedList<TreeNode<T>>();
}
public TreeNode<T> AddChild(T child)
{
TreeNode<T> childNode = new TreeNode<T>(child) { Parent = this };
this.Children.Add(childNode);
return childNode;
}
public IEnumerator<TreeNode<T>> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
}
public class TreeNodeEnum<T> : IEnumerator<TreeNode<T>>
{
int position = -1;
public List<TreeNode<T>> Nodes { get; set; }
public TreeNode<T> Current
{
get
{
try
{
return Nodes[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public TreeNodeEnum(List<TreeNode<T>> nodes)
{
Nodes = nodes;
}
public void Dispose()
{
}
public bool MoveNext()
{
position++;
return (position < Nodes.Count);
}
public void Reset()
{
position = -1;
}
}
I have added a complete solution and example using the NTree class above. I also added the "AddChild" method...
public class NTree<T>
{
public T data;
public LinkedList<NTree<T>> children;
public NTree(T data)
{
this.data = data;
children = new LinkedList<NTree<T>>();
}
public void AddChild(T data)
{
var node = new NTree<T>(data) { Parent = this };
children.AddFirst(node);
}
public NTree<T> Parent { get; private set; }
public NTree<T> GetChild(int i)
{
foreach (NTree<T> n in children)
if (--i == 0)
return n;
return null;
}
public void Traverse(NTree<T> node, TreeVisitor<T> visitor, string t, ref NTree<T> r)
{
visitor(node.data, node, t, ref r);
foreach (NTree<T> kid in node.children)
Traverse(kid, visitor, t, ref r);
}
}
public static void DelegateMethod(KeyValuePair<string, string> data, NTree<KeyValuePair<string, string>> node, string t, ref NTree<KeyValuePair<string, string>> r)
{
string a = string.Empty;
if (node.data.Key == t)
{
r = node;
return;
}
}
Using it
NTree<KeyValuePair<string, string>> ret = null;
tree.Traverse(tree, DelegateMethod, node["categoryId"].InnerText, ref ret);
There is also the possibility to use XML with LINQ:
Create XML tree in C# (LINQ to XML)
XML is the most mature and flexible solution when it comes to using trees and LINQ provides you with all the tools that you need.
The configuration of your tree also gets much cleaner and user-friendly as you can simply use an XML file for the initialization.
If you need to work with objects, you can use XML serialization:
XML serialization
Most trees are formed by the data you are processing.
Say you have a person class that includes details of someone’s
parents, would you rather have the tree structure as part of your
“domain class”, or use a separate tree class that contained links to
your person objects? Think about a simple operation like getting all
the grandchildren of a person, should this code be in the person
class, or should the user of the person class have to know about a
separate tree class?
Another example is a parse tree in a compiler…
Both of these examples show that the concept of a tree is part of the domain of the data and using a separate general-purpose tree at least doubles the number of objects that are created as well as making the API harder to program again.
We want a way to reuse the standard tree operations, without having to reimplement them for all trees, while at the same time, not having to use a standard tree class. Boost has tried to solve this type of problem for C++, but I am yet to see any effect for .NET to get it adapted.
If you are going to display this tree on the GUI, you can use TreeView and TreeNode. (I suppose technically you can create a TreeNode without putting it on a GUI, but it does have more overhead than a simple homegrown TreeNode implementation.)
Here is my implementation of a BST:
class BST
{
public class Node
{
public Node Left { get; set; }
public object Data { get; set; }
public Node Right { get; set; }
public Node()
{
Data = null;
}
public Node(int Data)
{
this.Data = (object)Data;
}
public void Insert(int Data)
{
if (this.Data == null)
{
this.Data = (object)Data;
return;
}
if (Data > (int)this.Data)
{
if (this.Right == null)
{
this.Right = new Node(Data);
}
else
{
this.Right.Insert(Data);
}
}
if (Data <= (int)this.Data)
{
if (this.Left == null)
{
this.Left = new Node(Data);
}
else
{
this.Left.Insert(Data);
}
}
}
public void TraverseInOrder()
{
if(this.Left != null)
this.Left.TraverseInOrder();
Console.Write("{0} ", this.Data);
if (this.Right != null)
this.Right.TraverseInOrder();
}
}
public Node Root { get; set; }
public BST()
{
Root = new Node();
}
}
Tree With Generic Data
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class Tree<T>
{
public T Data { get; set; }
public LinkedList<Tree<T>> Children { get; set; } = new LinkedList<Tree<T>>();
public Task Traverse(Func<T, Task> actionOnNode, int maxDegreeOfParallelism = 1) => Traverse(actionOnNode, new SemaphoreSlim(maxDegreeOfParallelism, maxDegreeOfParallelism));
private async Task Traverse(Func<T, Task> actionOnNode, SemaphoreSlim semaphore)
{
await actionOnNode(Data);
SafeRelease(semaphore);
IEnumerable<Task> tasks = Children.Select(async input =>
{
await semaphore.WaitAsync().ConfigureAwait(false);
try
{
await input.Traverse(actionOnNode, semaphore).ConfigureAwait(false);
}
finally
{
SafeRelease(semaphore);
}
});
await Task.WhenAll(tasks);
}
private void SafeRelease(SemaphoreSlim semaphore)
{
try
{
semaphore.Release();
}
catch (Exception ex)
{
if (ex.Message.ToLower() != "Adding the specified count to the semaphore would cause it to exceed its maximum count.".ToLower())
{
throw;
}
}
}
public async Task<IEnumerable<T>> ToList()
{
ConcurrentBag<T> lst = new ConcurrentBag<T>();
await Traverse(async (data) => lst.Add(data));
return lst;
}
public async Task<int> Count() => (await ToList()).Count();
}
Unit Tests
using System.Threading.Tasks;
using Xunit;
public class Tree_Tests
{
[Fact]
public async Task Tree_ToList_Count()
{
Tree<int> head = new Tree<int>();
Assert.NotEmpty(await head.ToList());
Assert.True(await head.Count() == 1);
// child
var child = new Tree<int>();
head.Children.AddFirst(child);
Assert.True(await head.Count() == 2);
Assert.NotEmpty(await head.ToList());
// grandson
child.Children.AddFirst(new Tree<int>());
child.Children.AddFirst(new Tree<int>());
Assert.True(await head.Count() == 4);
Assert.NotEmpty(await head.ToList());
}
[Fact]
public async Task Tree_Traverse()
{
Tree<int> head = new Tree<int>() { Data = 1 };
// child
var child = new Tree<int>() { Data = 2 };
head.Children.AddFirst(child);
// grandson
child.Children.AddFirst(new Tree<int>() { Data = 3 });
child.Children.AddLast(new Tree<int>() { Data = 4 });
int counter = 0;
await head.Traverse(async (data) => counter += data);
Assert.True(counter == 10);
counter = 0;
await child.Traverse(async (data) => counter += data);
Assert.True(counter == 9);
counter = 0;
await child.Children.First!.Value.Traverse(async (data) => counter += data);
Assert.True(counter == 3);
counter = 0;
await child.Children.Last!.Value.Traverse(async (data) => counter += data);
Assert.True(counter == 4);
}
}
I don't like a tree aproach. It gets things overcomplicated including search or dril-down or even ui controls populating.
I would suggest to use a very simple approach with IDictionary<TChild, TParent>. This also allows to have no connections between nodes or levels.
In case you need a rooted tree data structure implementation that uses less memory, you can write your Node class as follows (C++ implementation):
class Node {
Node* parent;
int item; // depending on your needs
Node* firstChild; //pointer to left most child of node
Node* nextSibling; //pointer to the sibling to the right
}