C# get nesting Level of Tree - c#

Let´s say I have two classes:
public Foo
{
public List<Foo> Childs { get; set; }
public Bar BarObj { get; set; }
public int Level { get; set; }
}
public Bar
{
public List<Foo> Childs { get; set; }
}
Now I want to get the nesting-level from a Collection of "Foo" Objects
my current working Method looks like this:
int currentLevel = 0;
public void ApplyNestingLevel(List<Foo> list)
{
foreach(var item in list)
{
item.Level = currentLevel;
if(item.Childs.Count > 0 || item.BarObj.Childs.Count > 0)
{
currentLevel++;
}
ApplyNestingLevel(item.Childs);
ApplyNestingLevel(item.BarObj.Childs);
}
}
how could I make this more "elegant/simple" ?

public void ApplyNestingLevel(Foo f)
{
ApplyNestingLevel(f, 0);
}
public void ApplyNestingLevel(Foo f, int level)
{
if(f == null) { return; }
f.Level = level
if(f.Childs != null) {
foreach(Foo child in f.Childs)
{
ApplyNestingLevel(child, level + 1);
}
}
if(f.BarObj != null && f.BarObj.Childs != null) {
foreach(Foo child in f.BarObj.Childs)
{
ApplyNestingLevel(child, level + 1);
}
}
}

Store a reference to the parent and make the Level property recursive.
I added an example and a couple other design suggestions in the code sample below. Hope this helps. FYI, this is pretty much straight out of the Gang of Four's design for the Composite Pattern, which should be required reading for anyone who is serious about OOP.
DoFactory .NET Composite Pattern
Design Patterns: Elements of Reusable Object-Oriented Software, on Amazon.com
public class Foo
{
public Foo(Foo parent = default(Foo))
{
this.parent = parent;
this.children = new List<Foo>();
}
private readonly Foo parent;
private readonly List<Foo> children;
public int Level { get { return ReferenceEquals(parent,null) ? 0 : parent.Level + 1; } }
// don't expose the actual list... see below for why
public IEnumerable<Foo> Children { get { foreach(Foo child in this.children) yield return child; } }
// instead of exposing the child object list
// declare an explicit method with any parameters
// necessary. this allows you to enforce the invariant
// condition that all objects in a children collection
// will have their parent reference set to their
// actual parent
public void AddChild()
{
Foo newChild = new Foo(parent:this);
this.children.Add(newChild);
}
// if you need the ability to remove items as well,
// you can expose a remove method too. Just make
// sure that you validate expected preconditions
public int RemoveChild(Foo childToRemove)
{
if(ReferenceEquals(childToRemove,null)) throw new ArgumentNullException("childToRemove");
if(!ReferenceEquals(this,childToRemove.parent)) throw new ArgumentException("The object cannot be removed because the current object is not the correct parent.","childToRemove");
return children.RemoveAll((Foo existentChild) => existentChild.Equals(childToRemove));
}
}

my version, i using extensions.
public static class EnumerableExtensions
{
/// <summary>Get max nesting level.</summary>
/// <param name="source">Source.</param>
/// <param name="children">Selector.</param>
/// <typeparam name="T">Type.</typeparam>
/// <returns><see cref="IEnumerable{T}"/>.</returns>
public static int GetMaxNestingLevel<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> children)
{
return source.SelectMany(x => GetNestingLevel(x, 0)).Max();
IEnumerable<int> GetNestingLevel(T source, int level)
{
if (children(source) != null)
{
return children(source).SelectMany(x => GetNestingLevel(x, level + 1));
}
else
{
return new List<int> { level }
}
}
}
}
than u can use it like
var max = Foo.Childs.GetMaxNestingLevel(x => x.Childs);
ps
mayby you net tests (NUnit)
using NUnit.Framework;
....
public class EnumerableExtensionsTests
{
private static IEnumerable GetMaxNestingLevelTestCases
{
get
{
yield return new TestCaseData(new int[] { 1, 2, 3, 4 }).Returns(4);
yield return new TestCaseData(new int[] { 4, 3, 2, 1 }).Returns(4);
yield return new TestCaseData(new int[] { 1, 10, 0, 1 }).Returns(10);
yield return new TestCaseData(new int[] { 1, 1, 1, 1 }).Returns(1);
yield return new TestCaseData(new int[] { 1, 1, 1, 2 }).Returns(2);
}
}
[TestCaseSource(nameof(GetMaxNestingLevelTestCases))]
public int GetMaxNestingLevelTest(ICollection<int> sourceNestingLevel)
{
var testSource = sourceNestingLevel.Select(x => new NestingLevelTestClass(x)).ToList();
return testSource.GetMaxNestingLevel(x => x.Children);
}
private class NestingLevelTestClass
{
public NestingLevelTestClass(int childrenLevel = 0)
{
if (childrenLevel != 0)
{
Children = new List<NestingLevelTestClass>
{
new NestingLevelTestClass(childrenLevel - 1),
};
}
}
public ICollection<NestingLevelTestClass> Children { get; set; }
}
}

Related

c# confused about base class inheritance

I am confused as to exactly how classes inherit methods from each other. I already understand inheritance from base classes, there is however, certain code from an example that I do not understand. It involves searching a Binary tree and I could not find any resources that better explain how the code is inherited.
My aim is to understand it so that I can use it to also searched a linkedlist.
If any one can refer me to any relevant literature that explains this particular area I would be grateful.
I have highlighted the code section that I dont really yet understand how it is inhertied. The specific section is posted first:
public Company Read(string bezeichnung)
{
return stri.Search(new Company() { Bezeichnung = bezeichnung });
}
Entire program:
using System;
using System.IO;
using System.Text;
using System.Net;
namespace CompanySearch
{
class Program
{
static void Main(string[] args)
{
StreamReader r = new StreamReader(#"C:\Users\chris\Desktop\algo\fuckit\unternehmen.csv", Encoding.Default);
Companies stri2 = new Companies(r);
while (true)
{
Console.Write("Unternehmensbezeichnung eingeben: ");
string name = Console.ReadLine();
if (string.IsNullOrEmpty(name))
break;
//Company konk = stri2.Read(name);
Company konk = new Company();
konk = stri2.Read(name);
if (konk == null)
Console.WriteLine("Unternehmen nicht gefunden!");
else
Console.WriteLine(konk + "\n");
}
}
}
public class Companies
{
private BinaryTree<Company> stri = new BinaryTree<Company>();
public Companies(StreamReader rp)
{
// Spaltenüberschriften auslesen
//var tokens = rp.ReadLine().Split(new char[] { ';' });
//if (tokens.Length != 3)
// throw new ArgumentException("More than 3 columns in company file");
string line;
while ((line = rp.ReadLine()) != null)
{
var tokens = line.Split(new char[]{';'});
//tokens = line.Split(new char[] { ';' });
stri.Add(new Company()
{Bezeichnung = tokens[0], Branche = tokens[1], Ort = tokens[2]});
}
rp.Close();
}
public Company Read(string bezeichnung)
{
return stri.Search(new Company()
{Bezeichnung = bezeichnung});
}
}
public class Company : IComparable<Company>
{
public string Bezeichnung
{
get;
set;
}
public string Branche
{
get;
set;
}
public string Ort
{
get;
set;
}
public int CompareTo(Company other)
{
return Bezeichnung.CompareTo(other.Bezeichnung);
}
public override string ToString()
{
return string.Format("Bezeichnung: {0}\tBranche: {1}\tOrt: {2}", Bezeichnung, Branche, Ort);
}
}
public enum TraverseModeEnum
{
PreOrder,
PostOrder,
InOrder,
ReverseInOrder
}
public class BinaryTree<T>
where T : IComparable<T>
{
private sealed class Node<TNode>
where TNode : IComparable<TNode> // TNode muss IComparable implementieren
{
public TNode Item
{
get;
set;
}
public Node<TNode> Left
{
get;
set;
}
public Node<TNode> Right
{
get;
set;
}
public int CompareTo(TNode other)
{
return Item.CompareTo(other);
}
}
private Node<T> root;
public int Count
{
get;
private set;
}
public TraverseModeEnum TraverseMode
{
get;
set;
}
public BinaryTree()
{
TraverseMode = TraverseModeEnum.PreOrder;
}
public void Add(T item)
{
if (root == null)
root = new Node<T>()
{Item = item};
else
addTo(root, item);
Count++;
}
public void AddRange(T[] items)
{
foreach (var item in items)
Add(item);
}
private void addTo(Node<T> node, T item)
{
if (item.CompareTo(node.Item) < 0)
{
if (node.Left == null)
node.Left = new Node<T>()
{Item = item};
else
addTo(node.Left, item);
}
else
{
if (node.Right == null)
node.Right = new Node<T>()
{Item = item};
else
addTo(node.Right, item);
}
}
public bool Contains(T item)
{
Node<T> node = root;
while (node != null)
{
int c = node.Item.CompareTo(item);
if (c == 0)
return true;
if (c > 0)
node = node.Left;
else
node = node.Right;
}
return false;
}
public T Search(T item)
{
Node<T> node = root;
while (node != null)
{
int c = node.Item.CompareTo(item);
if (c == 0)
return node.Item;
if (c > 0)
node = node.Left;
else
node = node.Right;
}
return default (T);
}
public void Clear()
{
root = null;
Count = 0;
}
public override string ToString()
{
string s = "";
int level = 0;
traverse(root, level, ref s);
return s;
}
private void traverse(Node<T> node, int level, ref string s)
{
if (node == null)
return;
bool reverse = TraverseMode == TraverseModeEnum.ReverseInOrder;
if (TraverseMode == TraverseModeEnum.PreOrder)
s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
traverse(reverse ? node.Right : node.Left, level + 2, ref s);
if (TraverseMode == TraverseModeEnum.InOrder || TraverseMode == TraverseModeEnum.ReverseInOrder)
s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
traverse(reverse ? node.Left : node.Right, level + 2, ref s);
if (TraverseMode == TraverseModeEnum.PostOrder)
s += "".PadLeft(level, ' ') + node.Item.ToString() + "\n";
}
}
}
The class BinaryTree<T> down in the code demands that T must implement IComparable<T>. Lots of list-ish classes make similar demands. If a type implements IComparable<T> it means two instances of a class can be compared to each other with the ComparetTo( T t1, T t2 ) method. This method returns an indication of which T is greater than, less than, or equal to the other. Realize that the greater than, less than, or equal to is entirely up to the type that implements the interface. It's principally used for sorting or otherwise locating things in a tree, list, or other structure based on the comparison.
Implementing an interface looks like class inheritance. The syntax is the same...but it's more like a contract, since an interface has no code to inherit. If you make a class that goes like:
class MyClass: IComparable<MyClass>
{
//--> stuff
}
...then you're obligated to have a publicly visible method with the signature:
int CompareTo( MyClass a, MyClass b )
{
//--> look at the two instances and make a determination...
}
The method can use any characteristics of the class to determine what makes a greater than, less than, or equal to b...and thereby control how it's going to be placed into a structure.
A class can inherit from only one other class...but it can implement as many interfaces as it needs. This is what, I'm guessing, looks like multiple inheritance.
a. There is no real inheritance in your code. Only the implementation of a standard interface, IComparable<T>. Implementing an interface is sometimes called inheritance but it is not the same. In this case it forces Company to implement the CompareTo() method.
b. The code you have a question about just creates a temporary object. You can rewrite it to something that might be easier to understand:
//return stri.Search(new Company() { Bezeichnung = bezeichnung });
var tempCompany = new Company() { Bezeichnung = bezeichnung };
return stri.Search(tempCompany);

How to drill into List and get their parentIds

I am facing an issue where I have to drill down through the list till I find the desired contentId. Once the contentId is matched, I need to get its ParentIds. I am able to get the contentId but not its ParentId.
Currently I am using recursion to get the ParentIds of a child node. But failed to get the desired results.
Can anyone make it run, or provide the correct code to get this issue fixed. I'm trying to get the childnode and its parentIds. I need to get the parentIds and then want to insert into a List.
I'm able to drill down into the loop but don't know how and when to store the parentIds into a list.
In this code, I am trying to get the parents of contentId "5".
class Program
{
static void Main(string[] args)
{
Program obj = new Program();
var data = obj.GetAllChildCats();
foreach (var item in data)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
public List<int> GetAllChildCats()
{
var ret = getdata();
var data = GetAllChildCats(4, ret.contentObjects, 0);
return data;
}
List<int> parentIdsList1 = new List<int>();
private List<int> GetAllChildCats(int id, ContentObjects data, int Parentid)
{
if (!string.IsNullOrEmpty(data.ContentObjectId.ToString()))
{
parentIdsList1.Add(Parentid);
if (data.ContentObjectId == id)
{
return parentIdsList1;
}
else
{
if (data.ChildContentObjects != null)
{
foreach (ContentObjects cat in data.ChildContentObjects)
{
GetAllChildCats(id, cat, data.ContentObjectId);
}
}
}
}
return parentIdsList1;
}
public Heirarchy getdata()
{
Heirarchy ret = new Heirarchy()
{
_id = 11,
contentObjects = new ContentObjects()
{
ContentObjectId = 1,
NodeId = 34,
ChildContentObjects = new List<ContentObjects>()
{
new ContentObjects() {
ContentObjectId=2,
NodeId=34,
ChildContentObjects= new List<ContentObjects>()
{
new ContentObjects() {
ContentObjectId=3,
NodeId=34,
ChildContentObjects= null
}
}
},
new ContentObjects() {
ContentObjectId=4,
NodeId=34,
ChildContentObjects= new List<ContentObjects>()
{
new ContentObjects() {
ContentObjectId=5,
NodeId=34,
ChildContentObjects= null
}
}
},
}
},
HierarchyId = 2
};
return ret;
}
}
public class Heirarchy
{
public int _id { get; set; }
public ContentObjects contentObjects { get; set; }
public int HierarchyId { get; set; }
}
public class ContentObjects
{
public int ContentObjectId { get; set; }
public int NodeId { get; set; }
public List<ContentObjects> ChildContentObjects { get; set; }
}
In this code, I am trying to get the parents of contentId "5".
This can be solved by a simple depth-first search. We just have to check the children's ID before digging deeper into the tree, so that we can still return the parent reference:
static void Main(string[] args)
{
Program obj = new Program();
var parents = obj.GetParentsOf(5, obj.getdata().contentObjects);
Console.WriteLine(parents.Count()); // yields 1
Console.WriteLine(parents.First().ContentObjectId); // yields 4
Console.ReadLine();
}
private IEnumerable<ContentObjects> GetParentsOf(int id, ContentObjects root)
{
if (root.ChildContentObjects != null)
{
foreach (ContentObjects c in root.ChildContentObjects)
{
// If a direct child has the requested ID, we are a parent.
if (c.ContentObjectId == id)
{
yield return root;
}
// Recurse deeper down.
foreach (ContentObjects found in GetParentsOf(id, c))
{
yield return found;
}
}
}
}
If, on the other hand, by "parents" you mean the complete path down the tree, we need to modify the method as follows. We again have a recursive depth-first search, but we insert our own id into the path when returning from a successful recursive step:
static void Main(string[] args)
{
Program obj = new Program();
var path = obj.GetPathTo(5, obj.getdata().contentObjects);
// prints 1, 4
foreach (ContentObjects o in path)
{
Console.WriteLine(o.ContentObjectId);
}
Console.ReadLine();
}
// returns null if id could not be found
private IEnumerable<ContentObjects> GetPathTo(int id, ContentObjects root)
{
if (root.ChildContentObjects != null)
{
foreach (ContentObjects c in root.ChildContentObjects)
{
if (c.ContentObjectId == id)
{
// If a direct child has the requested ID, we are the first parent.
return new[] { root };
}
else
{
// Recurse deeper down.
var found = GetPathTo(id, c);
if (found != null)
{
// We found something deeper down. Since we are part of the
// path, append own id.
return new[] { root }.Concat(found);
}
}
}
}
return null;
}

Check if List<T> element contains an item with a Particular Property Value

public class Item
{
public List<int> val { get; set; }
public double support { get; set; }
}
I declare variable:
List<Item> t = new List<Item>();
t.Add(new Item(){val = new List<int>(){1,2,3};support=.1);
var b = new Item();
b.val = t[0].val;
b.support=t[0].support;
t.Contain(b) // return false???
I'm try with linq
t.Any(a=>a.val==b.val) // I'm get error Expression cannot contain lambda expressions
3 possibilities come to mind:
You could implement IEquatable<T>:
public class Item: IEquatable<Item>
{
public List<int> val { get; set; }
public double support { get; set; }
public bool Equals(Item other)
{
return
this.support == other.support &&
this.val.SequenceEqual(other.val);
}
}
and now t.Contains(b) will return true.
If you cannot modify the Item class you could write a custom EqualityComparer:
public class ItemEqualityComparer : IEqualityComparer<Item>
{
private ItemEqualityComparer()
{
}
public static IEqualityComparer<Item> Instance
{
get
{
return new ItemEqualityComparer();
}
}
public bool Equals(Item x, Item y)
{
return
x.support == y.support &&
x.val.SequenceEqual(y.val);
}
public int GetHashCode(Item obj)
{
int hash = 27;
hash += (13 * hash) + obj.support.GetHashCode();
foreach (var item in obj.val)
{
hash += (13 * hash) + item.GetHashCode();
}
return hash;
}
}
and then t.Contains(b) will also return true.
Or if you prefer simply do it naively:
List<Item> t = new List<Item>();
t.Add(new Item { val = new List<int>(){1,2,3}, support=.1 });
var b = new Item();
b.val = t[0].val;
b.support = t[0].support;
bool equals = t.All(item => item.support == b.support && item.val.SequenceEqual(b.val));
Console.WriteLine(equals);
Your t.Any(a=>a.val == b.val) is correct.
The error you get is from the quick watch or expression window in the debugger, not from the compiler. Visual Studio's expression evaluator does not handle lambdas. However, it's still valid c# code, and will do what you want.
It's your earlier line that's a problem:
t.Add(new Item(){val = new List<int>(){1,2,3};support=.1);
This is a mixture of various different bits of syntax. It should be:
t.Add(new Item(){val = new List<int>(){1,2,3}, support=.1});
... although preferably with better property names, etc. Then the rest should work - although you need to do something with the result of Any. The Any call itself is valid. Here's a short but complete program which works:
using System;
using System.Collections.Generic;
using System.Linq;
public class Item
{
public List<int> Values { get; set; }
public double Support { get; set; }
}
class Test
{
static void Main()
{
List<Item> list = new List<Item>
{
new Item { Values = new List<int>{1, 2, 3},
Support = 0.1 }
};
var check = new Item { Values = list[0].Values,
Support = list[0].Support };
bool found = list.Any(a => a.Values == check.Values);
Console.WriteLine(found);
}
}
Note that this is performing a reference comparison between the two lists - if you created a different list with the same values (1, 2, 3), that wouldn't be found. You'd need to use a.Values.SequenceEqual(b.Values) or something similar.
Your Item class should implemenet the IEquatable interface:
class Item : IEquatable<Item>{
public List<int> val { get; set; }
public double support { get; set; }
public bool Equals(Item item){
return this.support.Equals(item.support) && this.val.SequenceEqual(item.val);
}
}
Then the Contains() method should work well.
You can correct your "t.Contain(b)" to t.Contains(b, new ItemEqualityComparer()) from System.Linq where ItemEqualityComparer will be your class, which will implement IEqualityComparer<Item>

Finding the root nodes of all the of a tree from a nodes in any generic list

This is a entity and i want to list all the children node for a given node in a generic function
public static List<T> BuildTree<T>(List<T> list, T selectNode string keyPropName, string parentPropName, string levelPropName, int level = 0)
{
List<T> entity = new List<T>();
foreach (T item in list)
{
}
return entity;
}
example of the entity structure
protected long _coakey;
protected long _parentkey;
protected string _coacode;
protected string _coacodeclient;
protected string _coaname;
protected int _coalevel;
[DataMember]
public long coakey
{
get { return _coakey; }
set { _coakey = value; this.OnChnaged(); }
}
[DataMember]
public long parentkey
{
get { return _parentkey; }
set { _parentkey = value; this.OnChnaged(); }
}
[DataMember]
public string coacode
{
get { return _coacode; }
set { _coacode = value; this.OnChnaged(); }
}
[DataMember]
public string coacodeclient
{
get { return _coacodeclient; }
set { _coacodeclient = value; this.OnChnaged(); }
}
[DataMember]
public string coaname
{
get { return _coaname; }
set { _coaname = value; this.OnChnaged(); }
}
[DataMember]
public int coalevel
{
get { return _coalevel; }
set { _coalevel = value; this.OnChnaged(); }
}
Your BuildTree<T> method cannot determine the structure of the tree unless it knows something about its structure. At a very minimum, I would suggest making a base class or interface that defines a tree node, and then change the BuildTree method to work specifically with those types of objects. Then, it will be able to figure out the tree structure. Each of you entity classes would have to implement that tree node interface or inherit from the tree node base class. For instance:
public abstract class TreeNodeBase
{
public long parentkey
{
get { return _parentkey; }
set { _parentkey = value; this.OnChanged(); }
}
protected long _parentkey;
}
public class MyEntityTreeNode : TreeNodeBase
{
public long coakey
{
get { return _coakey; }
set { _coakey = value; this.OnChanged(); }
}
protected long _coakey;
// etc...
}
// Note the generic type constraint at the end of the next line
public static List<T> BuildTree<T>(List<T> list, T selectNode, string keyPropName, string parentPropName, string levelPropName, int level) where T : TreeNodeBase
{
List<T> entity = new List<T>();
foreach (TreeNodeBase node in list)
{
long parentKey = node.parentkey;
// etc...
}
return entity;
}
Node class:
public class Node<TKey, TValue> where TKey : IEquatable<TKey>
{
public TKey Key { get; set; }
public TKey ParentKey { get; set; }
public TValue Data { get; set; }
public readonly List<Node<TKey, TValue>> Children = new List<Node<TKey, TValue>>();
}
TreeBuilder:
public static Node<TKey, TValue> BuildTree<TKey, TValue>(IEnumerable<Node<TKey, TValue>> list,
Node<TKey, TValue> selectNode)
where TKey : IEquatable<TKey>
{
if (ReferenceEquals(selectNode, null))
{
return null;
}
var selectNodeKey = selectNode.Key;
foreach (var childNode in list.Where(x => x.ParentKey.Equals(selectNodeKey)))
{
selectNode.Children.Add(BuildTree(list, childNode));
}
return selectNode;
}
Usage:
List<MyClass> list = ...
var nodes = list.Select(x => new Node<long, MyClass>
{
Key = x.MyKey,
ParentKey = x.MyParentKey,
Data = x
}).ToList();
var startNode = nodes.FirstOrDefault(x => x.Data.Stuff == "Pick me!");
var tree = BuildTree(nodes, startNode);
MyClass example:
public class MyClass
{
public long MyKey;
public long MyParentKey;
public string Name;
public string Text;
public string Stuff;
}
I have solved it my self hope it help you
public static List<T> BuildTree<T>(List<T> list, T selectedNode, string keyPropName, string parentPropName, int endLevel = 0, int level = 0)
{
List<T> entity = new List<T>();
Type type = typeof(T);
PropertyInfo keyProp = type.GetProperty(keyPropName);
string _selectedNodekey = keyProp.GetValue(selectedNode, null).ToString();
PropertyInfo parentProp = type.GetProperty(parentPropName);
foreach (T item in list)
{
string _key = keyProp.GetValue(item, null).ToString();
string _parent = parentProp.GetValue(item, null).ToString();
if (_selectedNodekey == _parent)
{
T obj = (T)Activator.CreateInstance(typeof(T));
obj = item;
entity.Add(obj);
if (level == endLevel && level!=0) break;
entity.AddRange(BuildTree<T>(list, obj, keyPropName, parentPropName, level + 1));
}
}
return entity;
}

add indexing to custom list

I have the following list:
public class MyQueue : IEnumerable<int>
{
private Node Head { get; set; }
private Node Tail { get; set; }
public MyQueue()
{
Head = null;
}
public void Add(int item)
{
Enqueue(item);
}
public void Enqueue(int item)
{
var newItem = new Node { Data = item };
if (Head == null)
{
Head = newItem;
Tail = newItem;
return;
}
Node last = Tail;
last.Next = newItem;
Tail = newItem;
}
public IEnumerator<int> GetEnumerator()
{
Node current = Head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private class Node
{
public int Data;
public Node Next;
}
}
There are other methods, but they do not matter in this scenario.
I'd like to add indexing to this list.
So I can do something like:
var q = new MyQueue() {1, 2};
Console.WriteLine(q[0]); //1
What do I need to implement?
you need to make a property like this:
public int this[int index]
{
get {
// code to return value
}
}
public int this[int index]
{
get
{
return this.Skip(index).FirstOrDefault();
}
}
You need to implement an indexer. An indexer enables you to access a class, struct or interface as if it were an array. The syntax is as follows:
public int this[int index] {
get {
// obtain the item that corresponds to this index
// return the item
}
set {
// set the value of the item that corresponds to
// index to be equal to the implicit parameter named "value"
}
}
Here's an explicit example for your case:
public class MyQueue : IEnumerable<int> {
// ...
public int this[int index] {
get {
if (index < 0 || index > this.Count() - 1) {
throw new ArgumentOutOfRangeException("index");
}
return this.Skip(index).First();
}
set {
if (index < 0) {
throw new ArgumentOutOfRangeException("index");
}
Node current = Head;
int i = 0;
while (current != null && i < index) {
current = current.Next; i++;
}
if (current == null) {
throw new ArgumentOutOfRangeException("index");
}
current.Data = value;
}
}
}
Implement the this operator.
Write a this property, like this: (pun intended)
public int this[int index] {
get {
return something;
}
//Optionally:
set {
something = value;
}
}
Also, you should probably implement IList<int>. (Note, though, that the Count property would require a loop)

Categories

Resources