I have a iterator pattern. But I want to make it generic. So that you can have strings and numbers. Because now you only can put strings in the list items.
So I have this:
public interface IIterator< out T>
{
void First();
T Next();
bool IsDone();
T CurrentItem();
}
public interface IAggregate< out T>
{
IIterator <T> CreateIterator();
}
}
public class Science : IAggregate<T>
{
private LinkedList<string> Subjects;
public Science()
{
Subjects = new LinkedList<string>();
Subjects.AddFirst("Maths");
Subjects.AddFirst("Comp. Sc.");
Subjects.AddFirst(99);// So this of course fails
}
public IIterator<T> CreateIterator()
{
return new ScienceIterator<T>(Subjects);
}
}
public class ScienceIterator : IIterator
{
private System.Collections.Generic.LinkedList<string> Subjects;
private int position;
public ScienceIterator(LinkedList<string> subjects)
{
this.Subjects = subjects;
position = 0;
}
public void First()
{
position = 0;
}
public string Next()
{
return Subjects.ElementAt(position++);
}
public bool IsDone()
{
if (position < Subjects.Count)
{
return false;
}
else
{
return true;
}
}
public string CurrentItem()
{
return Subjects.ElementAt(position);
}
}
So my question is, is this possible in the default C# collection? Or you have to make your own LinkedList?
Thank you
Related
fans of beautiful code.
I would like to ask my question by two ways. May be it will be useful to understand me.
1) There is code of 2 classes. One of them is nested. Nested class is used to get access to private fields of other one. I would like to get inherit class B:A{class BUnit:AUnit{}} which has the same functional but else has some more methods and fields in B and BUnits classes. How it can be done?
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a.Add();
a.Add();
bool res=a[0].Rename("1");//res=true;
res = a[1].Rename("1");//res= false;
Console.ReadKey();
}
}
class A
{
private List<AUnit> AUnits;
public AUnit this[int index] {get {return AUnits[index];}}
public A()//ctor
{
AUnits = new List<AUnit>();
}
public void Add()
{
this.AUnits.Add(new AUnit(this));
}
public class AUnit
{
private string NamePr;
private A Container;
public AUnit(A container)//ctor
{
NamePr = "Default";
this.Container = container;
}
public string Name { get { return this.NamePr; } }
public Boolean Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.AUnits)
{
if (unt.Name == newName) res = false;
}
if (res) this.NamePr = String.Copy(newName);
return res;
}
}
}
2) There is two very similar “things” – Class A and Class B. Is it possible to separate their common part, and then “inherit” this two “things” from it ? For example, I would like add some methods like GetUnitsCount() or RemoveUnit() and this methods are common for both. So I should “CopyPaste” this method to A and B but it is not good idea. It will be better to change their common part one time in one place. There is no important how it can be done – inheriting or interfaces or anything else. Important - how?
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a[0].objB.Add();
a[0].objB.Add();
a[0].objB[0].Val1 = 1;
int res = a[0].objB[0].Val1 + a[0].objB[0].Val2;
Console.ReadKey();
}
}
class A
{
private List<AUnit> Units;
public AUnit this[int index] {get {return Units[index];}}
public A()//ctor
{
Units = new List<AUnit>();
}
public void Add()
{
this.Units.Add(new AUnit(this));
}
public class AUnit
{
private string NamePr;
private A Container;
public B objB;
public AUnit(A container)//ctor
{
NamePr = "Default";
this.Container = container;
this.objB = new B();
}
public string Name { get { return this.NamePr; } }
public Boolean Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.Units)
{
if (unt.Name == newName) res = false;
}
if (res) this.NamePr = String.Copy(newName);
return res;
}
}
}
class B
{
private List<BUnit> Units;
public BUnit this[int index] { get { return Units[index]; } }
public B()//ctor
{
Units = new List<BUnit>();
}
public void Add()
{
this.Units.Add(new BUnit(this));
}
public class BUnit
{
private string NamePr;
private B Container;
public int Val1{get;set;}
public int Val2{get;set;}
public BUnit(B container)//ctor
{
NamePr = "Default";
this.Container = container;
this.Val1 = 10;
this.Val2 = 17;
}
public string Name { get { return this.NamePr; } }
public Boolean Rename(String newName)
{
Boolean res = true;
foreach (BUnit unt in this.Container.Units)
{
if (unt.Name == newName) res = false;
}
if (res) this.NamePr = String.Copy(newName);
return res;
}
}
}
Thank you for your attentions.
To answer your first question, the only thing you need to to to have BUnit inherit from AUnit is to qualify AUnit:
public class BUnit : A.AUnit
{
....
}
from there I believe your question is about basic inheritance which works no differently for nested classes. Nested classes are purely for organization - they are not inherited when you inherit the "containing" class.
This question already has answers here:
IEnumerable , IEnumerator vs foreach, when to use what [duplicate]
(3 answers)
Closed 6 years ago.
I have a simple class, Employee, and another class, Company, which contains an array of employees. The company class has 2 nested classes with iterators. One orders the items from first to last, and the second one reverses the order. The NormalEnumeration is the default. When I attempt to use ReverseOrder" in a foreach loop, I get this error:
foreach statement cannot operate on variables of type
'Zadanie_1.Company.ReverseEnumeration' because
'Zadanie_1.Company.ReverseEnumeration' does not contain a public
definition for 'GetEnumerator'
My questions is: How can I implement the custom iterators?
public class Employee
{
private string surname, position;
public string Stanowisko { get { return position; } }
public Employee (string nazwisko, string stanowisko)
{
this.surname = nazwisko;
this.position = stanowisko;
}
public override string ToString()
{
return string.Format("nazwisko: {0}, stanowisko: {1}", surname, position);
}
}
public class Company:IEnumerable
{
string name;
private Employee[] employeeArray;
public Company(string nazwa, Employee[] pracownicy)
{
this.name = nazwa;
this.employeeArray = pracownicy;
}
public IEnumerator GetEnumerator()
{
//foreach (Pracownik item in pracownicy)
//{
// yield return item;
//}
return new NormalEnumeration(this);
}
public IEnumerator Ordered()
{
return new NormalEnumeration(this);
}
public override string ToString()
{
return string.Format("Nazwa firmy: {0}, liczba pracowników: {1}", name, employeeArray.Length);
}
public class ReverseEnumeration : IEnumerator
{
Company f;
int counter;
public ReverseEnumeration(Company f)
{
this.f = f;
counter = f.employeeArray.Length;
}
public object Current
{
get
{
Console.WriteLine("Current");
return f.employeeArray[counter];
}
}
public bool MoveNext()
{
if (counter > 0)
{
Console.WriteLine("Move next:");
counter--;
return true;
}
else
return false;
}
public void Reset()
{
counter = f.employeeArray.Length;
}
}
public class NormalEnumeration : IEnumerator
{
Company f;
int counter = -1;
public NormalEnumeration(Company f)
{
this.f = f;
}
public object Current
{
get
{
Console.WriteLine("Current");
return f.employeeArray[counter];
}
}
public bool MoveNext()
{
if (counter >= f.employeeArray.Length-1)
return false;
else
{
counter++;
return true;
}
}
public void Reset()
{
counter = -1;
}
}
}
Comment under the question:
I tried to call the reverse iterator this way:
foreach (Employee item in new Company.ReverseEnumeration(instancenamehere)) {
Console.WriteLine(item);
}
For this to work, ReverseEnumration would have to implement IEnumerable. If you want to be able to modify the enumerator, just add a new property to the Company class.
public class Company : IEnumerable
{
public IEnumerator Enumerator { get; set; }
public IEnumerator GetEnumerator()
{
return Enumerator;
}
// other members
}
You can set the default enumerator in the constructor.
public Company(string nazwa, Employee[] pracownicy)
{
Enumerator = new NormalEnumeration(this);
// other stuff
}
You should extract your enumerators out of the Company class, because they don't use it's internals anyway. This will enable you to easily change enumerators from the outside.
var c = new Company(null, null);
c.Enumerator = new ReverseEnumeration(c);
I have an assignment to implement a linear linked list using generics in C# console application.
The class should also contain a print() method to print the elements of the list.
Conditions for Linear List are to be as a long type (CNodeLong) or String Type (CNodeString), both inherited from CNode with virtual function Print().
I have a problem implementing the printing method. I don't know where should it stand, and how to override it.
Here is my CNode class and CList class:
public class CNode<T>
{
private CNode<T> next;
private T item;
public CNode<T> Next
{
get { return next; }
set { next = value; }
}
public T Item
{
get { return item; }
set { item = value; }
}
public CNode(T item)
: this(item,null)
{
}
public CNode(T item, CNode<T> next)
{
this.item = item;
this.next = next;
}
}
class CList<T>
{
private CNode<T> first;
private CNode<T> last;
private int count;
public CNode<T> First
{
get { return first; }
}
public CNode<T> Last
{
get { return last; }
}
public int Count
{
get { return count; }
}
public CList(string strListName)
{
count = 0;
first = last = null;
}
}
You probably should override ToString method and add the virtual Print method to CNode.
(I've also added the PrintList method to CList):
public class CNode<T>
{
...
public override string ToString()
{
return item.ToString();
}
virtual public void Print()
{
Console.WriteLine(item);
}
}
class CList<T>
{
...
public void PrintList()
{
CNode<T> current = first;
while (current != null)
{
Console.WriteLine(current.ToString());
current = current.Next;
}
}
}
Then you can override the virtual method in the child classes:
public class CNodeString : CNode<string>
{
public CNodeString(string item) : base(item) { }
override public void Print()
{
Console.WriteLine("Printing from CNodeString");
base.Print();
}
}
public class CNodeLong : CNode<long>
{
public CNodeLong(long item) : base(item) { }
override public void Print()
{
Console.WriteLine("Printing from CNodeLong");
base.Print();
}
}
Here is a Basic Class with TheProperty in question:
class BasicClass {
public BasicClass() {
TheProperty = new Object();
Stamped = DateTime.Now;
}
public object TheProperty { get; set; }
public DateTime Stamped { get; private set; }
}
Here is the Basic List:
class BasicList {
private List<BasicClass> list;
public BasicList() {
list = new List<BasicClass>();
}
public BasicClass this[object obj] {
get { return list.SingleOrDefault(o => o.TheProperty == obj); }
}
public void Add(BasicClass item) {
if (!Contains(item.TheProperty)) {
list.Add(item);
}
}
public bool Contains(object obj) {
return list.Any(o => o.TheProperty == obj); // Picked this little gem up yesterday!
}
public int Count { get { return list.Count; } }
}
I'd like to add a class to BasicList that will return an array of items.
I could write it like this, using traditional C#:
public object[] Properties() {
var props = new List<Object>(list.Count);
foreach (var item in list) {
props.Add(item.TheProperty);
}
return props.ToArray();
}
...but how would I write that using a LINQ or Lambda query?
return list.Select(p=>p.TheProperty).ToArray()
Hi I am trying to create a directory structure using composite pattern. I have an interface IAsset which is implemented by the file and folder class. So both are an Asset. Now I want to loop through all the files in all the folders but I am getting the error message:
Program.IAsset is not enumerable
This error message is in the inner foreach loop of getassetSize() method.
public class Program
{
public interface IAsset
{
double GetAssetSize();
void AddAsset(IAsset a);
}
public class File : IAsset
{
public double Size { get; set; }
public double GetAssetSize()
{
return Size;
}
public void AddAsset(IAsset a)
{
Console.WriteLine("No asset can be added to a file");
}
}
public class Folder : IAsset
{
public double Size { get { return _size; } set { _size = value; } }
private double _size = 0;
public List<IAsset> list = new List<IAsset>();
public double GetAssetSize()
{
foreach (var asset in list)
{
foreach (var x in asset)
{
// _size = x.GetAssetSize();
}
}
return _size;
}
public void AddAsset(IAsset a)
{
list.Add(a);
}
}
To fit into the composite pattern IAsset would need to inherit IEnumerable<IAsset> or provide a member which implements it. For example:
public interface IAsset : IEnumerable<IAsset>
{
double GetAssetSize();
void AddAsset(IAsset a);
}
public class File : IAsset
{
...
public IEnumerator<IAsset> GetEnumerator()
{
return new IAsset[0].GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
public class Folder : IAsset
{
...
public IEnumerator<IAsset> GetEnumerator()
{
return this.list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Or this:
public interface IAsset
{
double GetAssetSize();
void AddAsset(IAsset a);
IEnumerable<IAsset> Assets { get; }
}
public class File : IAsset
{
...
public IEnumerator<IAsset> Assets
{
get { return new IAsset[0]; }
}
}
public class Folder : IAsset
{
...
public IEnumerator<IAsset> GetEnumerator()
{
get { return this.list; }
}
}
Assuming that you want to sum the size of the files in the directory, you have one too many loops going. This would do it...
public double GetAssetSize()
{
foreach (var asset in list)
{
_size += x.GetAssetSize();
}
return _size;
}