Ok, so im working on a programming exercise where i have to write my own implementation for a FIFO linkedlist. I have a set of unittests that im trying to satisfy. My implementation so far works reasonably well. The problem im facing however is with the Next property.
In the Unittests they want to be able to call the Next property like this.
List.Next.Next.Value
List.Next.Value
etc. My implementation returns the entire class instance if someone calls Next, however when someone calls Next in multiple statements then the second statement will no longer have a fresh instance and the test fails.
My implementation:
using System.Collections;
using System.Collections.Generic;
public class SimpleLinkedList<T> : IEnumerable<T>
{
public class Node
{
public T Data { get; set; }
public Node Next { get; set; }
}
private Node First = null;
private Node Last = null;
public SimpleLinkedList(T value)
{
AddNode(value);
}
public SimpleLinkedList(IEnumerable<T> values)
{
foreach (var value in values)
{
AddNode(value);
}
}
public T Value {
get {
return First != null ? First.Data : default(T);
}
}
public SimpleLinkedList<T> Next {
get {
if (First.Next != null)
{
First = First.Next;
return this;
}
return null;
}
}
public SimpleLinkedList<T> Add(T value)
{
AddNode(value);
return this;
}
public IEnumerator<T> GetEnumerator()
{
var current = First;
while (current.Next != null)
{
yield return First.Data;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
void AddNode(T value)
{
Node _newNode = new Node() { Data = value };
if (First == null)
{
First = _newNode;
Last = First;
}
else
{
Last.Next = _newNode;
Last = Last.Next;
}
}
}
Failing unittest:
[Fact]
public void From_enumerable()
{
var list = new SimpleLinkedList<int>(new[] { 11, 7, 5, 3, 2 });
Assert.Equal(11, list.Value);
Assert.Equal(7, list.Next.Value);
Assert.Equal(5, list.Next.Next.Value);
Assert.Equal(3, list.Next.Next.Next.Value);
Assert.Equal(2, list.Next.Next.Next.Next.Value);
}
The unittests fails on the assert 5. Because in the statement before it Next has allready been called and the state of the object has been altered.
Ive tried keeping an internal 'Current' property to return instead of the First. But then im running into the problem, how do i know when to restart Current?
Im at a loss how to proceed from here.
I have pretty complex structure:
public static List<state> states = new List<state>();
public class state : List<situation> { }
public class situation {
//public rule rule; //another complex object
public int pos;
public string term;
public situation(/*rule rule,*/ string terminal, int pointPosition) {
//this.rule = rule;
this.term = terminal;
this.pos = pointPosition;
}
}
In my program i generate new state objects what must be added to states list. But only if here is no same state in this list (order of situation objects in state list is don't matter and can be different in two state what is equal in fact).
I tryed this:
states.Add(new state());
states[0].Add(new situation("#", 0));
state s = new state();
s.Add(new situation("#", 0));
if (states.Contains(s)) {
Console.WriteLine("HODOR"); //not performed
}
Looks like Contains don't work right with custom objects, so i must create some custom method.
I can just compare each objects and each fields but... it's look like pretty tedious and ugly solution. May be here is some better way to do this?
Override Equals in your situation class and implement your own equality i.e :
public class situation
{
public string Terminal
{
get{ return term;}
}
public int Pos
{
get{ return pos;}
}
public override bool Equals(object obj)
{
bool result;
situation s = obj as situation;
if (s != null)
{
result = Terminal.Equals(s.Terminal) && Pos == s.Pos;
}
return result;
}
}
I'm also added this:
public class state : List<situation> {
public override bool Equals(object obj) {
state s = obj as state;
if (s != null) {
foreach (situation situation in s) {
if (!this.Contains(situation)) { return false; }
}
foreach (situation situation in this) {
if (!s.Contains(situation)) { return false; }
}
return true;
}
return false;
}
}
So my example works.
I've got problem using generics. I'm creating an interface called IProblem, where each problem has results (answers) and a result (if it is correct)
public interface IProblem<T>
{
ushort ResultCount { get; }
T[] Results { get; }
bool IsCorrect();
}
public abstract class ProblemBase<T> : IProblem<T>
{
private T[] _results;
private ushort? _resultCount;
public ushort ResultCount
{
get
{
if (_resultCount == null) throw new ArgumentNullException("_resultCount");
return (ushort)_resultCount;
}
protected set
{
if (_resultCount != value)
_resultCount = value;
}
}
public T[] Results
{
get
{
if (_results == null)
_results = new T[ResultCount];
return _results;
}
}
public abstract bool IsCorrect();
}
This is an example where I create an arithmetic problem, called ProblemA. T is decimal because the array datatype should be decimal (anothers problems maybe might have string, or int)
public class ProblemA: ProblemBase<decimal>
{
private decimal _number1;
private decimal _number2;
private Operators _operator;
public decimal Number1
{
get { return _number1; }
set { _number1 = value; }
}
public decimal Number2
{
get { return _number2; }
set { _number2 = value; }
}
public Operators Operator
{
get { return _operator; }
set { _operator = value; }
}
public decimal Result
{
get { return Results[0]; }
set { Results[0] = value; }
}
public ProblemA()
{
this.ResultCount = 1;
}
public override bool IsCorrect()
{
bool result;
switch (_operator)
{
case Operators.Addition:
result = this.Result == (this.Number1 + this.Number2);
break;
case Operators.Subtract:
result = this.Result == (this.Number1 - this.Number2);
break;
case Operators.Multiplication:
result = this.Result == (this.Number1 * this.Number2);
break;
case Operators.Division:
result = this.Result == (this.Number1 / this.Number2);
break;
default:
throw new ArgumentException("_operator");
}
return result;
}
}
I'm using MVVM, so I'd like to have a ViewModel for each problem where contains ProblemBase<T> as property, but how it's a generic, I guess it will be a problem if a put in IProblemViewModel as generic.
public interface IProblemViewModel : IViewModel
{
ProblemBase<T> Problem { get; set; }
}
I said this because later a plan to use a ObservableCollection<IProblemViewModel>, so I'm not sure if there's no problem if I write IProblemViewModel or IProblemViewModel<T>.
Thanks in advance.
Maybe I haven't understood this perfectly, but is this what you are after?
ObservableCollection<IProblemViewModel<object>> collection = new ObservableCollection<IProblemViewModel<object>>
{
new ProblemViewModel<DerivedResult>(),
new ProblemViewModel<OtherResult>()
};
This can be achieved by declaring the generic argument as covariant.
You could also change the collection to
ObservableCollection<IProblem<BaseType>>
and just have it accept a specific result chain. In this example, DerivedResult and OtherResult must then inherit from BaseType to fit into the collection.
The big caveat is that primitive types don't fit into this hierarchy, in any way. You will have to wrap them in IProblem<IntResult> and so on.
Of course, you could implement a simple carrier, for example Boxer which would box any value type instead of implementing one for each type.
One last caveat: It's not possible to have a 'set' property on a covariant type, so IProblemViewModel can only support get.
A complete, compilable example:
class Program
{
public interface IProblem<out T>
{
ushort ResultCount { get; }
T[] Results { get; }
bool IsCorrect();
}
public class ProblemBase<T> : IProblem<T>
{
private T[] _results;
private ushort? _resultCount;
public ushort ResultCount
{
get
{
if (_resultCount == null) throw new ArgumentNullException("_resultCount");
return (ushort)_resultCount;
}
protected set
{
if (_resultCount != value)
_resultCount = value;
}
}
public T[] Results
{
get
{
if (_results == null)
_results = new T[ResultCount];
return _results;
}
}
public bool IsCorrect()
{
return true;
}
}
public interface IProblemViewModel<out T>
{
IProblem<T> Problem { get; }
}
public class BaseResult
{
}
public class DerivedResult : BaseResult
{
}
public class OtherResult : BaseResult
{
}
public class ProblemViewModel<T> : IProblemViewModel<T>
{
public IProblem<T> Problem
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
static void Main(string[] args)
{
ObservableCollection<IProblemViewModel<object>> collection = new ObservableCollection<IProblemViewModel<object>>
{
new ProblemViewModel<DerivedResult>(),
new ProblemViewModel<OtherResult>()
//, new ProblemViewModel<int>() // This is not possible, does not compile.
};
}
}
Your view model interface could be defined like this:
public interface IProblemViewModel<T> : IViewModel
{
//No reason to use the base here instead of the interface
IProblem<T> Problem { get; set; }
}
I'm not sure if you are planning on binding the Problem to an interface in WPF or Silverlight, but if you are make sure that Problem also implements INotifyPropertyChanged. Binding to non Dependency Properties on objects that don't implement INotifyPropertyChanged causes the a memory leak where the object will never be released. You can find more info on the leak here: http://support.microsoft.com/kb/938416
EDIT: Added answer to comment.
You are correct that having IProblemViewModel<T> would stop you using it in an ObservableCollection if you intend to show more than one type of <T>. However since when you are binding it doesn't really matter what the objects type is when you bind to it why not just make the collection an ObservableCollection<IViewModel>?
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
}