using System.Collections.Generic;
public static class ExtensionMethods
public static string Join(this IEnumerable<string> source, string delimiter = ";")
return string.Join(delimiter, source);
public interface INode<T>
INode<T> ParentNode { get; }
ICollection<INode<T>> ChildNodes { get; }
bool HasChildren { get; }
int TotalChildren { get; }
void SetParentNode(INode<T> child);
void AddChildNode(INode<T> child);
void RemoveChildNode(INode<T> child);
public class Node<T> : INode<T>
private INode<T> parentNode;
private List<INode<T>> childNodes;
childNodes = new List<INode<T>>();
public INode<T> ParentNode
public ICollection<INode<T>> ChildNodes
return childNodes.Count > 0;
public void AddChildNode(INode<T> child)
child.SetParentNode(this);
public void RemoveChildNode(INode<T> child)
childNodes.Remove(child);
child.SetParentNode(null);
public void SetParentNode(INode<T> parent)
public static void Main()
var cities = new List<string>{"Toronto", "Vancouver", "Calgary"};
var expected = "Toronto,Vancouver,Calgary";
var actual = cities.Join(",");
Console.WriteLine(String.Format("Join extensation method test: expected={0}, actual={1}, passed={2}", expected, actual, expected == actual));
NodeClassUsageWithCandadianCitiesAndProvinces();
public static int Dispatch(string operation, int a, int b)
throw new ArgumentException("invalid argument");
public static int Dispatch1(string operation, int a, int b)
Dictionary<string, Func<int, int, int>> operations = new Dictionary<string, Func<int, int, int>>();
operations.Add("add", (x, y) => x + y);
operations.Add("subtract", (x, y) => x - y);
operations.Add("multiply", (x, y) => x * y);
operations.Add("divide", (x, y) => x / y);
Func<int, int, int> func;
if (operations.TryGetValue(operation, out func))
throw new ArgumentException("Invalid argument");
public static void TestDispatch1()
Console.WriteLine("Testing Dispatch1 methods...");
int actual = Dispatch1("add", 2, 3);
Console.WriteLine(String.Format("Add Operation test: expected={0}, actual={1}, passed={2}", expected, actual, expected == actual));
actual = Dispatch1("subtract", 2, 3);
Console.WriteLine(String.Format("Subtract Operation test: expected={0}, actual={1}, passed={2}", expected, actual, expected == actual));
actual = Dispatch1("multiply", 2, 3);
Console.WriteLine(String.Format("Multiply Operation test: expected={0}, actual={1}, passed={2}", expected, actual, expected == actual));
actual = Dispatch1("divide", 6, 3);
Console.WriteLine(String.Format("Divide Operation test: expected={0}, actual={1}, passed={2}", expected, actual, expected == actual));
catch (ArgumentException ex)
Console.WriteLine(String.Format("Invalid operation test: expected=invalid argument, actual={0}, passed={1}", ex.Message, expected == actual));
Console.WriteLine("-- End of tests ---");
public static void NodeClassUsageWithCandadianCitiesAndProvinces()
Node<string> canada = new Node<string>("Canada");
Node<string> ontario = new Node<string>("Ontario");
Node<string> quebec = new Node<string>("Quebec");
canada.AddChildNode(ontario);
canada.AddChildNode(quebec);
Node<string> toronto = new Node<string>("Toronto");
Node<string> ottawa = new Node<string>("Ottawa");
ontario.AddChildNode(toronto);
ontario.AddChildNode(ottawa);
Node<string> montreal = new Node<string>("Montreal");
Node<string> quebecCity = new Node<string>("Quebec City");
quebec.AddChildNode(montreal);
quebec.AddChildNode(quebecCity);
Console.WriteLine(canada.Value);
Console.WriteLine(ontario.ParentNode.Value);
Console.WriteLine(toronto.ParentNode.Value);
Console.WriteLine(quebecCity.ParentNode.Value);
Console.WriteLine(canada.HasChildren);
Console.WriteLine(canada.TotalChildren);
Console.WriteLine(ontario.HasChildren);
Console.WriteLine(ontario.TotalChildren);
Console.WriteLine(toronto.HasChildren);
Console.WriteLine(toronto.TotalChildren);