Sei sulla pagina 1di 12

13

Collection Objects
Earlier we used an array in a foreach. If the array had three members, the foreach got executed
three times and each time the variable i had a different value. The concept described below is
called a collection class. It is a class that returns a value each time till the values run out, thus
making it easier for us to iterate through the array.

a.cs

public class zzz

public static void Main()

yyy f = new yyy();

foreach (string i in f)

class yyy

Compiler Error      
a.cs(6,1): error CS1579: foreach statement cannot operate on variables of type ‘yyy’ because
‘yyy’ does not contain a definition for ‘GetEnumerator’, or it is inaccessible

To use yyy in a foreach as a collection class, foreach requires a function GetEnumerator.

a.cs

public class zzz

public static void Main()

yyy f = new yyy();

foreach (string i in f)

class yyy

public int GetEnumerator()

Compiler Error

a.cs(6,1): error CS1579: foreach statement cannot operate on variables of type 'yyy' because 'int'
does not contain a definition for 'MoveNext', or it is inaccessible

a.cs(13,12): error CS0161: 'yyy.GetEnumerator()': not all code paths return a value
Foreach obviously tries to execute the function called GetEnumerator. This function should not
return an int but something else as the error suggests.

a.cs

using System.Collections;

public class zzz

public static void Main()

yyy f = new yyy();

foreach (string i in f)

class yyy

public IEnumerator GetEnumerator()

return new xxx();

class xxx : IEnumerator

}
Compiler Error

a.cs(19,7): error CS0535: ‘xxx’ does not implement interface member


‘System.Collections.IEnumerator.MoveNext()’

a.cs(19,7): error CS0535: ‘xxx’ does not implement interface member


‘System.Collections.IEnumerator.Reset()’

a.cs(19,7): error CS0535: ‘xxx’ does not implement interface member


‘System.Collections.IEnumerator.Current’

IEnumerator is an interface which has three functions MoveNext, Reset and Current and xxx has
to implement all of them to remove the compiler errors.

a.cs

using System.Collections;

public class zzz

public static void Main()

yyy f = new yyy();

foreach (string i in f)

System.Console.WriteLine(i);

class yyy

public IEnumerator GetEnumerator()


{

return new xxx();

class xxx : IEnumerator

public bool MoveNext()

System.Console.WriteLine(“MoveNext”);

return true;

public void Reset()

System.Console.WriteLine(“Reset”);

public object Current

get

System.Console.WriteLine(“Current”);

return “hi”;

}
}

Run the program and you will notice that the output does not stop. It goes on forever.

IEnumerator is an interface which belongs to the namespace System.Collections. foreach first


calls the function GetEnumerator from yyy. It expects this function to return an object like
IEnumerator. It then calls the function MoveNext from this returned object. If MoveNext returns
true it knows that there is some data to be read and it calls the property Current to access this
data. From Current the get accessor gets called which always returns “hi” in our case. Then
MoveNext gets called and if it returns false, we quit out of the foreach statement. As MoveNext
always returns true, we go into an indefinite loop.

a.cs

using System.Collections;

public class zzz

public static void Main()

yyy f = new yyy();

foreach (string i in f)

System.Console.WriteLine(i);

class yyy

public IEnumerator GetEnumerator()

{
return new xxx();

class xxx : IEnumerator

public string []  a = new string[3] {“hi” , “bye” ,”no”};

public int i = -1;

public bool MoveNext()

i++;

System.Console.WriteLine(“MoveNext” + i);

if ( i == 3)

return false;

else

return true;

public void Reset()

System.Console.WriteLine(“Reset”);

public object Current

get
{

System.Console.WriteLine(“Current “ + a[i]);

return a[i];

Output

MoveNext0

Current hi

hi

MoveNext1

Current bye

bye

MoveNext2

Current no

no

MoveNext3

We have created an array a which has 3 members and initialized them respectively to hi, bye and
no by giving the strings in {} immediately after the new. Each time MoveNext gets called the
variable i is increased by 1. If the value of i is 3, we have no more strings to return and thus we
return false, else we return true. The variable i keeps track of how many times the function
MoveNext is being called. As MoveNext returns true, Current gets called which returns a string
from the array using i as the offset. Thus we can iterate through the entire array depending upon
the length.

a.cs

using System.Collections;
public class zzz

public static void Main()

yyy f = new yyy(“This is Great”);

foreach (string i in f)

System.Console.WriteLine(i);

class yyy

string t;

public yyy(string t1)

t = t1;

public IEnumerator GetEnumerator()

return new xxx(t);

}
class xxx : IEnumerator

public string [] a;

public xxx(string t3)

char [] b = new char[1];

b[0] = ‘ ‘;

a = t3.Split(b);

public int i = -1;

public bool MoveNext()

i++;

System.Console.WriteLine(“MoveNext “ + i);

if ( i == a.Length)

return false;

else

return true;

public void Reset()

System.Console.WriteLine(“Reset”);

}
public object Current

get

System.Console.WriteLine(“Current “ + a[i]);

return a[i];

Output

MoveNext 0

Current This

This

MoveNext 1

Current is

is

MoveNext 2

Current Great

Great

MoveNext 3

Pretty big program. At the time of creating a yyy object we are passing a string to the
constructor. Thus the yyy constructor gets called first. The constructor stores this string in
variable t. The foreach statement calls GetEnumerator which now creates a xxx object passing it
the string through t. The constructor of xxx now gets called. Every string class has a member
function called Split. Split will break up a string on certain characters which we call delimiters.
In this case, we want our string to be broken up whenever we encounter a space. The Split
function requires an array of chars which it can use as a delimiter. The reason it requires an array
is because we may have more than one char that we would like to break the string on. Like
earlier, the array a now contains the array of strings. The last change is the condition in the if
statement. Earlier we used a constant number, now we use a member, Length, of an array which
stores the length of the array or the number of members. Thus the class yyy can now be used as a
collection class which enumerates the individual words in the string. The function Reset for
some reason never ever gets called.

Potrebbero piacerti anche