Enumerating the Members of a Collection

Introduction

A collection is a group of values. To create these values, you have various options. If the collection of values or objects you want to use will need many operations, you can either create a collection class or use an existing class.

Starting a Collection

By default, a collection contains some values or objects whose type is known in advance, such as a collection of numbers or a collection of strings. To start the collection, you can create an array of values, such as an array of strings, in it. The collection could be started as follows:

public class Collection
{
    string[] cities;
}

Of course, you should (must) initialize the array. You can initial the array where it is declared. Here is an example:

public class Collection
{
    string[] cities = new string[5];
}

The reason you must initialize an array is because its items must be known when an array is created. In fact, when an array is created, each element receives a value. If you only provide the size of the array, each item receives a default value, which is 0 for numbers, false for a Boolean array, or an empty string for a collection of strings. This is illustrated in the following code:

using static System.Console;

public class Collection
{
    string[] cities;

    public Collection()
    {
        cities = new string[5];

        Show();
    }

    void Show()
    {
        WriteLine("Name: " + cities[0]);
        WriteLine("Name: " + cities[1]);
        WriteLine("Name: " + cities[2]);
        WriteLine("Name: " + cities[3]);
        WriteLine("Name: " + cities[4]);
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();
        
        WriteLine("================================");
        return;
    }
}

This would produce:

Name:
Name:
Name:
Name:
Name:
================================
Press any key to continue . . .

Of course, if you want to show the values outside the class, you should make the method public. Here is an example:

using static System.Console;

public class Collection
{
    string[] cities;

    public Collection()
    {
        cities = new string[5];
    }

    public void Show()
    {
        WriteLine("Name: " + cities[0]);
        WriteLine("Name: " + cities[1]);
        WriteLine("Name: " + cities[2]);
        WriteLine("Name: " + cities[3]);
        WriteLine("Name: " + cities[4]);
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        names.Show();
        
        WriteLine("================================");
        return;
    }
}

Adding an Item to a Collection

As you may know already, the above code proves that, once an array has been created, no new item can be added to it: You can only replace the value of an existing item using its position. Here are examples:

using static System.Console;

public class Collection
{
    string[] cities;

    public Collection()
    {
        cities = new string[5];
    }

    public void Add(string city)
    {
        cities[2] = city;
    }

    public void Show()
    {
        WriteLine("Cities");
        WriteLine("-------------------");
        WriteLine("Name: " + cities[0]);
        WriteLine("Name: " + cities[1]);
        WriteLine("Name: " + cities[2]);
        WriteLine("Name: " + cities[3]);
        WriteLine("Name: " + cities[4]);
        WriteLine("================================");
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        names.Add("Sydney");
        names.Show();

        names.Add("Chicago");
        names.Show();

        return;
    }
}

This would produce:

Cities
-------------------
Name:
Name:
Name: Sydney
Name:
Name:
================================
Cities
-------------------
Name:
Name:
Name: Chicago
Name:
Name:
================================
Press any key to continue . . .

Getting to an Item by its Position

In the above code, we assumed that the Add() method would always set the argument to the same position. An alternative is to pass another argument that holds the position at which to replace the item. This can be done as follows:

using static System.Console;

public class Collection
{
    string[] cities;

    public Collection()
    {
        cities = new string[6];
    }

    public void Add(int index, string city)
    {
        cities[index] = city;
    }

    public void Show()
    {
        WriteLine("Cities");
        WriteLine("-------------------");
        WriteLine("Name: " + cities[0]);
        WriteLine("Name: " + cities[1]);
        WriteLine("Name: " + cities[2]);
        WriteLine("Name: " + cities[3]);
        WriteLine("Name: " + cities[4]);
        WriteLine("Name: " + cities[5]);
        WriteLine("================================");
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        names.Add(3, "Kuala Lumpur");
        names.Add(0, "Dar es Salaam");
        names.Add(5, "Sydney");
        names.Add(2, "Santiago");
        names.Add(4, "Chicago");
        names.Add(1, "Wellington");
        
        names.Show();

        return;
    }
}

This would produce:

Cities
-------------------
Name: Dar es Salaam
Name: Wellington
Name: Santiago
Name: Kuala Lumpur
Name: Chicago
Name: Sydney
================================
Press any key to continue . . .

On the other hand, to access an item, such as to display its value, you can pass its position to a method and let the method return the value at that position. This technique would allow you to access the items outside the collection class. Here is an example:

using static System.Console;

public class Collection
{
    string[] cities;

    public Collection()
    {
        cities = new string[6];
    }

    public void Add(int index, string city)
    {
        cities[index] = city;
    }

    public string Get(int index)
    {
        return cities[index];
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        names.Add(3, "Kuala Lumpur");
        names.Add(0, "Dar es Salaam");
        names.Add(5, "Sydney");
        names.Add(2, "Santiago");
        names.Add(4, "Chicago");
        names.Add(1, "Wellington");
        
        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("City: " + names.Get(5));
        WriteLine("================================");
        
        return;
    }
}

The Index of this Item

As seen when studying indexed properties, to combine the ability to add an item and to locate it using an index, the C# language provides the this indexer. This means that, in your collection class, you can create a this property of the same type as the array. Pass an integral argument to its square brackets. In the get clause, return the array-based item at that position. In the set clause, assign value to the array-based element at that position. This can be done as follows:

public class Collection
{
    string[] cities;

    . . .

    public string this[int index]
    {
        get
        {
            return cities[index];
        }
        set
        {
            cities[index] = value;
        }
    }
}

After doing this, you can assign or specify a value or object to the collection based on the desired position of the item, and you can retrieve a value or object based on a position. Here is an example:

using static System.Console;

public class Collection
{
    string[] cities;

    public Collection()
    {
        cities = new string[6];
    }

    public void Add(int index, string city)
    {
        cities[index] = city;
    }

    public string Get(int index)
    {
        return cities[index];
    }

    public string this[int index]
    {
        get
        {
            return cities[index];
        }
        set
        {
            cities[index] = value;
        }
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        names[3] = "Kuala Lumpur";
        names[0] = "Dar es Salaam";
        names[5] = "Sydney";
        names[2] = "Santiago";
        names[4] = "Chicago";
        names[1] = "Wellington";
        
        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("================================");

        return;
    }
}

For our example, we don't need the previous Get() method and you can remove it.

The Size of a Collection

As mentioned in previous lessons and sections, an array has a fixed number of items, and a new item can only replace another at an existing position. If you want to add the items consecutively, you can use a monitoring counter so that, when the collection starts, this integer-based counter is set to 0. This can be done as follows:

using static System.Console;

public class Collection
{
    string[] cities;
    int size;

    public Collection()
    {
        size = 0;
        cities = new string[6];
    }

    public void Add(int index, string city)
    {
        cities[index] = city;
    }

    public string this[int index]
    {
        get { return cities[index];  }
        set { cities[index] = value; }
    }

    public void Summarize()
    {
        WriteLine("Collection Size: " +  size);
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        WriteLine("Cities");
        WriteLine("-------------------");

        names.Summarize();
        
        WriteLine("================================");
        return;
    }
}

This would produce:

Cities
-------------------
Collection Size: 0
================================
Press any key to continue . . .

When a new item is added, you can increase the counter. Here is an example:

using static System.Console;

public class Collection
{
    string[] cities;
    int size;

    public Collection()
    {
        size = 0;
        cities = new string[6];
    }

    public void Add(int index, string city)
    {
        cities[index] = city;
        size++;
    }

    public string this[int index]
    {
        get { return cities[index];  }
        set { cities[index] = value; }
    }

    public void Summarize()
    {
        WriteLine("Collection Size: " +  size);
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        WriteLine("Cities");
        WriteLine("-------------------");
        names.Add(0, "Ottawa");
        names.Summarize();
        WriteLine("-------------------");
        names.Add(1, "Accra");
        names.Summarize();
        WriteLine("-------------------");
        names.Add(2, "Jakarta");
        names.Summarize();

        WriteLine("================================");
        return;
    }
}

This would produce:

Cities
-------------------
Collection Size: 1
-------------------
Collection Size: 2
-------------------
Collection Size: 3
================================
Press any key to continue . . .

To be able to access the monitoring counter outside the class, you can create a public method or property that returns it. By tradtion in the .NET Framework, this member is created as a property and is named Count. Here is an example:

using static System.Console;

public class Collection
{
    string[] cities;
    int size;

    public Collection()
    {
        size = 0;
        cities = new string[6];
    }

    public void Add(int index, string city)
    {
        cities[index] = city;
        size++;
    }

    public string this[int index]
    {
        get { return cities[index];  }
        set { cities[index] = value; }
    }

    public int Count
    {
        get
        {
            return size;
        }
    }
}

public class Exercise
{
    public static void Main()
    {
        Collection names = new Collection();

        WriteLine("Cities");
        WriteLine("-------------------");
        names.Add(0, "Ottawa");
        WriteLine("Collection Size: " + names.Count);
        
        WriteLine("-------------------");
        names.Add(1, "Accra");
        WriteLine("Collection Size: " + names.Count);
        WriteLine("-------------------");
        names.Add(2, "Jakarta");
        WriteLine("Collection Size: " + names.Count);

        WriteLine("================================");
        return;
    }
}

In this case, and by tradition, the Add() method may not need an index parameter. This means that you can create an Add() method that takes a new item as argument, positions it at the current position of the counter, and increases the counter. This can be done as follows:

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 . . .

Introduction to .NET Iterations

Introduction to the Collections Namespaces

To use a collection, you can create a collection class. To assist you in creating and managing a collection of values or objects, the .NET Framework provides a namespace named System.Collections. The main goal of that namespace is to provide all the routine operations performed on a list of items, whether a list of primitive values or a collection of composite objects.

The System.Collections namespace contains classes used to create a collection for specific object. To allow you to create a collection for any type of object, the .NET Framework provides another namespace named System.Collections.Generics. This is a large namespace with many interfaces and various collection classes. Of course, to use a class from this namespace, if you are writing your code in a class, you either should (must) qualify the name of its class or add the namespace in the top section of the document. This can be done as follows:

using System.Collections.Generic;

public class Fundamentalist
{

}

Introduction to Collections Interfaces

To assist you to create collections, both the System.Collections and the System.Collections.Generics namespaces includes many interfaces. One of the most regular ways to check the members of a collection consists of visiting each and taking the appropriate action.

To support the ability to visit each item of a collection, the .NET Framework provides some mechanism through two interfaces named IEnumerator and IEnumerable.

Introduction to the IEnumerator Interface

The IEnumerator interface provides the means of identifying the class that holds a sample of the items that will be enumerated. This interface is equipped with one property and two methods. To use the functionalities provided by the IEnumerator interface, you must create a class that implements it. You can start the class as follows:

public class Enumerator : IEnumerator
{
}

If your collection is an array-based list, you can start by declaring the base array in the class: Here is an example:

public class Enumerator : IEnumerator
{
    private double[] numbers;
}

If the collection is not array-based, you can declare a variable for the class that would be enumerated.

The role of the enumerator is to act on a collection. For this reason, the class should be prepared to receive an external collection. This can be done by passing it to a constructor of the enumerator. Here is an example:

public class Enumerator : IEnumerator
{
    private double[] numbers;

    public Enumerator(double[] list)
    {
    }
}

The internal collection would be used in the enumerator class. The external collection would be the source of the values of the list that would be enumerated. For these reasons, you can/should initialize the internal collection with the values of the external list. This can be done as follows:

public class Enumerator : IEnumerator
{
    private double[] numbers;

    public Enumerator(double[] list)
    {
        this.numbers = list;
    }
}

The Current Item of an Enumeration

In the previous lesson, when introducing some techniques of creating a list, we saw that you should have a type of tag, as a field, that allows you to monitor the item that is being currently accessed or used in the list. This is particularly valuable when visiting the members of the collection. The IEnumerator interface provides a property that is used to identify the current member of the list. This property is called Current. Because the current item is meant to be viewed only, the Current property is a read-only member. Based on the rules of abstract classes, remember that you must implement all members of an interface in the class that is based on it.

To implement the Current property, you can define its get accessor to return the item at the current position. This can be done as follows:

public class Enumerator : IEnumerator
{
    private double[] numbers;
    private int cur;

    public Enumerator(double[] list)
    {
        this.numbers = list;
    }

    public object Current
    {
        get { return numbers[cur]; }
    }
}

Resetting the Tag of the Current Item

Although you should be able to identify the current item at any time, when the application starts, before the collection can be enumerated, the tag that is used to monitor the current item should be set to a value before the beginning of the count. This can be done by setting the tag to -1. Here is an example:

public class Enumerator : IEnumerator
{
    private double[] numbers;
    private int cur;

    public Enumerator(double[] list)
    {
        this.numbers = list;
        cur = -1;
    }

    public Object Current
    {
        get { return numbers[cur]; }
    }
}

While the collection is being used, at one moment you may want to reset the tag of the current item to its original position. To support this operation, the IEnumerator interface is equipped with a method named Reset. Its syntax is:

void Reset();

When implementing this method, simply assign a non-existing value, which is usually -1, to the monitoring tag of the current item. This can be done as follows:

public class Enumerator : IEnumerator
{
    private double[] numbers;
    private int cur;

    public Enumerator(double[] list)
    {
        this.numbers = list;
        cur = -1;
    }

    public object Current
    {
        get { return numbers[cur]; }
    }

    public void Reset()
    {
        cur = -1;
    }
}

When using the implementer of the IEnumerator interface, if you try accessing an item beyond the maximum number of items, the compiler would throw an IndexOutOfRangeException exception. For this reason, when anticipating a bad behavior, you should catch this exception when implementing the Current property.

Moving to the Next Item in the Enumerator

In the previous lesson, we saw that, when using the items of a collection, one way you could locate one item from another was to be able to jump from one item to the next. This operation is also very important when enumerating a collection. To support this operation, the IEnumerator interface is quipped with the MoveNext() method. Its syntax is:

bool MoveNext();

When implementing this method, first increment the tag that monitors the current item of the collection. After incrementing the tag, check whether it is lower than the total number of items. If it is, return true. Otherwise, return false. This can be done as follows:

public class Enumerator : IEnumerator
{
    private double[] numbers;
    private int cur;

    public Enumerator(double[] list)
    {
        this.numbers = list;
        cur = -1;
    }

    public Object Current
    {
        get { return numbers[cur]; }
    }

    public void Reset()
    {
        cur = -1;
    }

    public bool MoveNext()
    {
        cur++;
        if (cur < numbers.Length)
            return true;
        else
            return false;
    }
}

An Enumerable Collection

Introduction

The IEnumerator interface is used to set up a collection for enumeration. The IEnumerator does not provide the functionality necessary to use foreach. The next step is to implement another interface called IEnumerable.

While the IEnumerator interface is used to identify the class that holds each value that will be visited, the IEnumerable interface is used to communicate with the collection whose items will be enumerated. For this reason, when implementing this class, you should provide the means of accessing the external collection. This can be done by passing a collection of the class that holds the values, to a constructor of the IEnumerable implementer.

Getting the Enumerator

To implement the IEnumerable interface, start by deriving a class from it. While the class implemented by the IEnumerator interface represents an object, the class that implements the IEnumerable interface is a collection. Here is an example:

public class Enumerable : IEnumerable
{
}

The new class does not know what collection it will be asked to enumerate. For this reason, in the new class, you should declare a member variable of the class that holds the values that will be enumerated. If the collection is array-based, you can create the field as follows:

public class Enumerable : IEnumerable
{
    private double[] numbers;
}

Eventually, when instantiating the IEnumerable implementer, you will need to pass it a collection of values. To make this possible, you can create a method in the new class and pass that collection of objects. Here is an example:

public class Enumerable : IEnumerable
{
    private double[] numbers;

    public void Identify(double[] values)
    {
    }
}

In this method, you can assign the member variable to the argument. You should also assign each member of the argument to its equivalent of the member of the argument. This can be done with a for loop as follows:

public class Enumerable : IEnumerable
{
    private double[] numbers;

    public void Identify(double[] values)
    {
        numbers = values;
        for (int i = 0; i < values.Length; i++)
            numbers[i] = values[i];
    }
}

For Each Member of an Enumerable

Introduction

To support the use of the foreach loop, the IEnumerable interface is equipped with (only) a method named GetEnumerator that you must implement. The IEnumerable.GetEnumerator() method returns an IEnumerator object. When implementing this method, you can return an object of the class that implements the IEnumerator interface, passing it the collection that was declared in the IEnumerable implementer. This can be done as follows: 

public class Enumerable : IEnumerable
{
    private double[] numbers;

    public void Identify(double[] values)
    {
        numbers = values;
        for (int i = 0; i < values.Length; i++)
            numbers[i] = values[i];
    }

    public IEnumerator GetEnumerator()
    {
        return new Enumerator(numbers);
    }
}

Using foreach

After implementing the IEnumerator and the IEnumerable interfaces, you can then use the foreach loop. To start, you must prepare the collection and its items for processing. Here is an example:

public class Exercise
{
    static int Main(string[] args)
    {
        double[] numbers = new double[5];
        numbers[0] = 224.52;
        numbers[1] = 60.48;
        numbers[2] = 1250.64;
        numbers[3] = 8.86;
        numbers[4] = 1005.36;

        return 0;
    }
}

To enumerate the collection, declare a variable based on the implementer of the IEnumerable and pass the collection to its constructor. Once this is done, you can then use the foreach. Here is an example:

using System;
using System.Collections;

public class Enumerator : IEnumerator
{
    private double[] numbers;
    private int cur;

    public Enumerator(double[] list)
    {
        this.numbers = list;
        cur = -1;
    }

    public Object Current
    {
        get { return numbers[cur]; }
    }

    public void Reset()
    {
        cur = -1;
    }

    public bool MoveNext()
    {
        cur++;
        if (cur < numbers.Length)
            return true;
        else
            return false;
    }
}

public class Enumerable : IEnumerable
{
    private double[] numbers;

    public void Identify(double[] values)
    {
        numbers = values;
        for (int i = 0; i < values.Length; i++)
            numbers[i] = values[i];
    }

    public IEnumerator GetEnumerator()
    {
        return new Enumerator(numbers);
    }
}

public class Exercise
{
    static int Main(string[] args)
    {
        double[] numbers = new double[5];
        numbers[0] = 224.52;
        numbers[1] = 60.48;
        numbers[2] = 1250.64;
        numbers[3] = 8.86;
        numbers[4] = 1005.36;

        Enumerable coll = new Enumerable();
        
        coll.Identify(numbers);
        foreach (double d in coll)
            Console.WriteLine("Item {0}", d); ;

        return 0;
    }
}

Yielding to Get an Enumerator

The IEnumerable interface allows you to connect your collection to the class that handles its enumeration. Instead of implementing that interface, the C# language provides a shortcut through a contextual keyword named yield. The yield keyword allows a method to indicate that it performs an iteration for a collection class. To use yield, you have many options.

In the previous sections, we saw that you can implement the IEnumerable interface and create a method that returns an IEnumerator object. As a shortcut, you can create a method name GetEnumerator that returns an IEnumerator object. In the method, you can use a while loop to visit each member of the collection. Every time you visit a member, return it to the compiler. To do this, combine the yield and the return keywords. Inside the loop, you must find a way to navigate from one member of the collection to the next. To do this, you can use a local variable that keeps a count and increment itself. Here is an example:

using System;
using System.Collections;

public class ListNumbers
{
    private double[] numbers;
    private int size;

    public ListNumbers()
    {
        size = 0;
        numbers = new double[10];
    }

    public int Count
    {
        get
        {
            return size;
        }
    }

    public void Add(double number)
    {
        numbers[size] = number;
        size++;
    }

    public double this[int index]
    {
        get
        {
            return numbers[index];
        }
        set
        {
            numbers[index] = value;
            size++;
        }
    }

    public IEnumerator GetEnumerator()
    {
        int counter = 0;

        while (counter < Count)
        {
            yield return numbers[counter];
            counter++;
        }
    }
}

public class Exercise
{
    public static int Main()
    {
        ListNumbers nbrs = new ListNumbers();

        nbrs.Add(9.08);
        nbrs.Add(79.13);
        nbrs.Add(4.803);
        nbrs.Add(725.45);
        nbrs.Add(2937.468);

        Console.WriteLine("--- Using \"for\"---");
        for (int i = 0; i < nbrs.Count; i++)
            Console.WriteLine("Number: {0}", nbrs[i]);

        Console.WriteLine("--- Using \"foreach\"---");
        foreach (double n in nbrs)
            Console.WriteLine("Number: {0}", n);

        Console.WriteLine();
        return 0;
    }
}

This would produce:

--- Using "for"---
Number: 9.08
Number: 79.13
Number: 4.803
Number: 725.45
Number: 2937.468
--- Using "foreach"---
Number: 9.08
Number: 79.13
Number: 4.803
Number: 725.45
Number: 2937.468

Press any key to continue . . .

Our collection class uses a simple type (a double type). Still, you can use the same approach if the items of the collection are composite (class type).

Yielding An Enumerable

Another technique to use yield consists of creating a method that returns an IEnumerable object. Inside the method, you can use a while loop to access each member of the collection and return it. Once again, you combine yield and return to indicate that the method is an iterator that returns a member of the collection. At the end of each loop, find a way to get to the next member unless you have gotten to the end of the collection. As done previously, you can use a local variable to take care of this. Here is an example:

using System;
using System.Collections;

public class ListNumbers
{
    private double[] numbers;
    private int size;

    public ListNumbers()
    {
        size = 0;
        numbers = new double[5];
    }

    public int Count
    {
        get
        {
            return size;
        }
    }

    public double this[int index]
    {
        get
        {
            return numbers[index];
        }
        set
        {
            numbers[index] = value;
            size++;
        }
    }

    public IEnumerable AllNumbers()
    {
        int counter = 0;

        while (counter < Count)
        {
            yield return numbers[counter];
            counter++;
        }
    }
}

In this example, we explicitly created a method named AllNumbers. If you do this, when using the collection, make sure you call this method. Here is an example:

public class Exercise
{
    public static int Main()
    {
        ListNumbers nbrs = new ListNumbers();

        nbrs[0] = 9.08;
        nbrs[1] = 79.13;
        nbrs[2] = 4.803;
        nbrs[3] = 725.45;

        Console.WriteLine("--- Using \"for\"---");
        for (int i = 0; i < nbrs.Count; i++)
            Console.WriteLine("Number: {0}", nbrs[i]);

        Console.WriteLine("--- Using \"foreach\"---");
        foreach (double n in nbrs.AllNumbers())
            Console.WriteLine("Number: {0}", n);

        Console.WriteLine();
        return 0;
    }
}

This would produce:

--- Using "for"---
Number: 9.08
Number: 79.13
Number: 4.803
Number: 725.45
--- Using "foreach"---
Number: 9.08
Number: 79.13
Number: 4.803
Number: 725.45

Press any key to continue . . .

You can create the method as a static one. In this case you can pass the collection class as argument. When calling the method, use the name of the collection class to call the method and pass the variable as argument. Here is an example where the method is created in the body of the collection class:

using System;
using System.Collections;

public class ListNumbers
{
    private double[] numbers;
    private int size;

    public ListNumbers()
    {
        size = 0;
        numbers = new double[5];
    }

    public int Count
    {
        get
        {
            return size;
        }
    }

    public double this[int index]
    {
        get
        {
            return numbers[index];
        }
        set
        {
            numbers[index] = value;
            size++;
        }
    }

    public static IEnumerable AllNumbers(ListNumbers lst)
    {
        int counter = 0;

        while (counter < lst.Count)
        {
            yield return lst.numbers[counter];
            counter++;
        }
    }
}

public class Exercise
{
    public static int Main()
    {
        ListNumbers nbrs = new ListNumbers();

        nbrs[0] = 9.08;
        nbrs[1] = 79.13;
        nbrs[2] = 4.803;
        nbrs[3] = 725.45;

        Console.WriteLine("--- Using \"for\"---");
        for (int i = 0; i < nbrs.Count; i++)
            Console.WriteLine("Number: {0}", nbrs[i]);

        Console.WriteLine("--- Using \"foreach\"---");
        foreach (double n in ListNumbers.AllNumbers(nbrs))
            Console.WriteLine("Number: {0}", n);

        Console.WriteLine();
        return 0;
    }
}

Here is an example where the method is created in the body of the class that calls it (the class that contains the Main() function):

using System;
using System.Collections;

public class ListNumbers
{
    private double[] numbers;
    private int size;

    public ListNumbers()
    {
        size = 0;
        numbers = new double[5];
    }

    public int Count
    {
        get
        {
            return size;
        }
    }

    public double this[int index]
    {
        get
        {
            return numbers[index];
        }
        set
        {
            numbers[index] = value;
            size++;
        }
    }
}

public class Exercise
{
    public static IEnumerable AllNumbers(ListNumbers lst)
    {
        int counter = 0;

        while (counter < lst.Count)
        {
            yield return lst[counter];
            counter++;
        }
    }

    public static int Main()
    {
        ListNumbers nbrs = new ListNumbers();

        nbrs[0] = 9.08;
        nbrs[1] = 79.13;
        nbrs[2] = 4.803;
        nbrs[3] = 725.45;

        Console.WriteLine("--- Using \"for\"---");
        for (int i = 0; i < nbrs.Count; i++)
            Console.WriteLine("Number: {0}", nbrs[i]);

        Console.WriteLine("--- Using \"foreach\"---");
        foreach (double n in AllNumbers(nbrs))
            Console.WriteLine("Number: {0}", n);

        Console.WriteLine();
        return 0;
    }
}

Remember that, although we are using a simple type in our example, you can apply the same solution to a collection of objects.


Previous Copyright © 2008-2019, FunctionX Next