Generic Collection Iteration
Generic Collection Iteration
A Generic Collection
Introduction
Consider the following class from our previous lesson:
using static System.Console; public class Collection { string[] cities; int size; public Collection() { size = 0; cities = new string[6]; } public void Add(string city) { cities[size] = city; size++; } public string this[int index] { get { return cities[index]; } set { cities[index] = value; } } public int Count => size; } public class Exercise { public static void Main() { Collection names = new Collection(); names.Add("Ottawa"); names.Add("Accra"); names.Add("Jakarta"); names.Add("Bonn"); names.Add("Mexico City"); names.Add("Brisbane"); WriteLine("Cities"); WriteLine("-------------------"); WriteLine("City: " + names[0]); WriteLine("City: " + names[1]); WriteLine("City: " + names[2]); WriteLine("City: " + names[3]); WriteLine("City: " + names[4]); WriteLine("City: " + names[5]); WriteLine("-------------------"); WriteLine("Collection Size: " + names.Count); WriteLine("================================"); return; } }
This would produce:
Cities ------------------- City: Ottawa City: Accra City: Jakarta City: Bonn City: Mexico City City: Brisbane ------------------- Collection Size: 6 ================================ Press any key to continue . . .
In the above class, you can create a collection of only strings and not other type. In the real world, you should be able to create a collection of any type. Your probable first thought is to create a different collection class for each type. This is not professional because there are as many types as sand on the floor. A professional alternative is to create a generic class that can be used to create a collection of any type.
As you may know already, to create a generic class, you can add <> to its name. The class can start as follows:
public class Collection<T>
{
}
After doing it, and based on our Collection class, throughout the class, you can substitute our string type with the parameter type. Here is an example:
public class Collection<GenericType> { GenericType[] cities; int size; public Collection() { size = 0; cities = new GenericType[6]; } public void Add(GenericType city) { cities[size] = city; size++; } public GenericType this[int index] { get { return cities[index]; } set { cities[index] = value; } } public int Count => size; }
When declaring a variable for the class, you should (must) add or specify a parameter type. Here is an example:
using static System.Console; public class Collection<GenericType> { GenericType[] cities; int size; public Collection() { size = 0; cities = new GenericType[6]; } public void Add(GenericType city) { cities[size] = city; size++; } public GenericType this[int index] { get { return cities[index]; } set { cities[index] = value; } } public int Count => size; } public class Exercise { public static void Main() { Collection<string> names = new Collection<string>(); names.Add("Ottawa"); names.Add("Accra"); names.Add("Jakarta"); names.Add("Bonn"); names.Add("Mexico City"); names.Add("Brisbane"); WriteLine("Cities"); WriteLine("-------------------"); WriteLine("City: " + names[0]); WriteLine("City: " + names[1]); WriteLine("City: " + names[2]); WriteLine("City: " + names[3]); WriteLine("City: " + names[4]); WriteLine("City: " + names[5]); WriteLine("-------------------"); WriteLine("Collection Size: " + names.Count); WriteLine("================================"); return; } }
You may remember that, by tradition, the parameter type is named T. This would be done as follows:
public class Collection<T> { T[] cities; int size; public Collection() { size = 0; cities = new T[6]; } public void Add(T city) { cities[size] = city; size++; } public T this[int index] { get { return cities[index]; } set { cities[index] = value; } } public int Count => size; }
A Generic Enumerable Collection
Instead of creating a generic collection class from scratch, the .NET Framework provides a generic interface named IEnumerable. This interface is inherits from an interface of the same name from the System.Collections namespace. The System.Collections.Generic.IEnumerable interface starts as follows:
public interface IEnumerable<out T> : System.Collections.IEnumerable
To benefit from this interface, create a class that implements it. Both the name of the class and the interface must have parameter type. The class would start as follows:
using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { }
The System.Collections.Generic.IEnumerable<> interface is equipped with only one member, which is a method named GetEnumerator. Your class must implement that method. Even if you are not planning to use it, you must provide at least a skeleton code for it. This can be done as follows:
using System.Collections;
using System.Collections.Generic;
public class Collection<T> : IEnumerable<T>
{
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
throw new System.NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new System.NotImplementedException();
}
}
We also know that you can start the items of a collection class with an array. This can be done as follows:
using System.Collections; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; public Collection() { items = new T[5]; } IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new System.NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } }
From what we have learned so far about collection classes, you should provide a way to count the items of the collection. This can be taken care of as follows:
using System.Collections; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; int size; public Collection() { size = 0; items = new T[5]; } public virtual int Count { get { return size; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new System.NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } }
You should also provide a way to add items to a collection. Here is an example:
using System.Collections; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; int size; public Collection() { size = 0; items = new T[5]; } public virtual int Count { get { return size; } } public void Add(T item) { items[size] = item; size++; } IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new System.NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } } public class Exercise { public static void Main() { Collection<string> names = new Collection<string>(); names.Add("Bamako"); names.Add("San Francisco"); names.Add("Minsk"); names.Add("Tokyo"); names.Add("La Paz"); } }
You should also provide a way to get or retrieve a value from an object of the class. You can do this with a Get() method. Here is an example:
using System.Collections; using static System.Console; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; int size; public Collection() { size = 0; items = new T[5]; } public virtual int Count { get { return size; } } public void Add(T item) { items[size] = item; size++; } public T Get(int index) { return items[index]; } IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new System.NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } } public class Exercise { public static void Main() { Collection<string> names = new Collection<string>(); names.Add("Bamako"); names.Add("San Francisco"); names.Add("Minsk"); names.Add("Tokyo"); names.Add("La Paz"); WriteLine("Cities"); WriteLine("-------------------"); WriteLine("City: " + names.Get(0)); WriteLine("City: " + names.Get(1)); WriteLine("City: " + names.Get(2)); WriteLine("City: " + names.Get(3)); WriteLine("City: " + names.Get(4)); WriteLine("---------------------"); WriteLine("Collection Size: " + names.Count); WriteLine("================================"); return; } }
This would produce:
Cities ------------------- City: Bamako City: San Francisco City: Minsk City: Tokyo City: La Paz --------------------- Collection Size: 5 ================================ Press any key to continue . . .
Or, better, you can create a this indexer. This can be done as follows:
using System.Collections; using static System.Console; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; int size; public Collection() { size = 0; items = new T[5]; } public virtual int Count { get { return size; } } public void Add(T item) { items[size] = item; size++; } public T Get(int index) { return items[index]; } public T this[int index] { get { return items[index]; } set { items[index] = value; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new System.NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } } public class Exercise { public static void Main() { Collection<string> names = new Collection<string>(); names[0] = "Bamako"; names[1] = "San Francisco"; names[2] = "Minsk"; names[3] = "Tokyo"; names[4] = "La Paz"; WriteLine("Cities"); WriteLine("-------------------"); WriteLine("City: " + names[0]); WriteLine("City: " + names[1]); WriteLine("City: " + names[2]); WriteLine("City: " + names[3]); WriteLine("City: " + names[4]); WriteLine("---------------------"); WriteLine("Collection Size: " + names.Count); WriteLine("================================"); return; } }
Enumerating an Enumerable
If you have an Add() method and an indexer, you can use a loop to access each item of the collection, in which case each item can be accessed by its index. Here is an example:
using System.Collections; using static System.Console; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; int size; public Collection() { size = 0; items = new T[5]; } public virtual int Count { get { return size; } } public void Add(T item) { items[size] = item; size++; } public T Get(int index) { return items[index]; } public T this[int index] { get { return items[index]; } set { items[index] = value; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new System.NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { throw new System.NotImplementedException(); } } public class Exercise { public static void Main() { Collection<string> names = new Collection<string>(); names.Add("Bamako"); names.Add("San Francisco"); names.Add("Minsk"); names.Add("Tokyo"); names.Add("La Paz"); WriteLine("Cities"); WriteLine("-------------------"); int i = 0; while(i < names.Count) { WriteLine("City: " + names[i]); i++; } WriteLine("================================"); return; } }
On the other hand, the lone member of the System.Collections.Generic.IEnumerable<> interface, the GetEnumerator method, makes it possible for a class that implements that interface to use the foreach loop on the items of a collection. This can be taken care of as follows:
using System.Collections; using static System.Console; using System.Collections.Generic; public class Collection<T> : IEnumerable<T> { T[] items; int size; public Collection() { size = 0; items = new T[5]; } public virtual int Count => size; } public void Add(T item) { items[size] = item; size++; } public T Get(int index) => items[index]; public T this[int index] { get { return items[index]; } set { items[index] = value; } } IEnumerator<T> IEnumerable<T>.GetEnumerator() { int counter = 0; while (counter < size) { yield return items[counter]; counter++; } } IEnumerator IEnumerable.GetEnumerator() { int counter = 0; while (counter < size) { yield return items[counter]; counter++; } } } public class Exercise { public static void Main() { Collection<string> names = new Collection<string>(); names.Add("Bamako"); names.Add("San Francisco"); names.Add("Minsk"); names.Add("Tokyo"); names.Add("La Paz"); WriteLine("Cities"); WriteLine("-------------------"); foreach(string city in names) WriteLine("City: " + city); WriteLine("---------------------"); WriteLine("Collection Size: " + names.Count); WriteLine("================================"); return; } }
|
||
Previous | Copyright © 2008-2019, FunctionX | Next |
|