Ienumerator: Provides interfaces that can be traversed in common sets, including current, movenext (), and reset (). In this example, current returns the object type.
Ienumerable: exposes an ienumerator that supports traversal in a common set.
Ienumerator <t>: inherits from ienumerator. It has the current attribute and returns the T type.
Ienumerable <t>: inherits from ienumerable, exposes an ienumerator <t>, and supports traversing in generic sets.
1. To make the custom set type support foreach access, you must implement the ienumerable interface.
2. In many cases, we have discussed why the newly added generic interface ienumerable <t> should inherit ienumerable to ensure compatibility. Theoretically, all generic interfaces must inherit from all non-generic interfaces. For example. NET 1.1 has a method that receives ienumerable parameters. When transplanted to a new environment, we pass in an ienumerable <t> parameter, which is also acceptable, they all perform enumeration.
However, ilist <t> does not inherit from the ilist interface, because if you want ilist <t> to inherit ilist, to implement the ilist <int> class, you need to implement two insert methods. One is the void insert (INT index, int item) of the ilist <int> ), the other is the void insert (INT index, object item) of ilist. This is an interface that can insert object-type data into the ilist <int> set. This is incorrect, so do not inherit.
The difference between ienumerable <t> is that it only acts as an "output", that is, we only retrieve data from it, so there is no confusion described above.
3. The example below describes how to use
First, there is a person class:
Public class person
{
Public Person (string fname, string lname)
{
This. firstname = fname;
This. lastname = lname;
}
Public String firstname;
Public String lastname;
}
The first method is to implement the people set:
Public class people: ienumerable
{
Private person [] _ people;
Public people (person [] parray)
{
_ People = new person [parray. Length];
For (INT I = 0; I <parray. length; I ++)
{
_ People [I] = parray [I];
}
}
Public ienumerator getenumerator ()
{
Return new peopleenum (_ people );
}
}
Public class peopleenum: ienumerator
{
Public person [] _ people;
// Enumerators are positioned before the first element
// Until the first movenext () call.
Int position =-1;
Public peopleenum (person [] list)
{
_ People = List;
}
Public bool movenext ()
{
Position ++;
Return (position <_ people. Length );
}
Public void reset ()
{
Position =-1;
}
Public object current
{
Get
{
Try
{
Return _ people [position];
}
Catch (indexoutofrangeexception)
{
Throw new invalidoperationexception ();
}
}
}
}
Second, let people implement the ienumerator interface:
Public class people: ienumerable, ienumerator
{
Private person [] _ people;
Int position =-1;
Public people (person [] parray)
{
_ People = new person [parray. Length];
For (INT I = 0; I <parray. length; I ++)
{
_ People [I] = parray [I];
}
}
# Region ienumerable members
Public ienumerator getenumerator ()
{
Return this;
}
# Endregion
# Region ienumerator members
Public object current
{
Get
{
Try
{
Return _ people [position];
}
Catch (indexoutofrangeexception)
{
Throw new indexoutofrangeexception ();
}
}
}
Public bool movenext ()
{
Position ++;
Return (position <_ people. Length );
}
Public void reset ()
{
Position =-1;
}
# Endregion
}
The third method specifies the type with the generic type:
Public class people: ienumerable <person>, ienumerator <person>
{
Private person [] _ people;
Int position =-1;
Public people (person [] parray)
{
_ People = new person [parray. Length];
For (INT I = 0; I <parray. length; I ++)
{
_ People [I] = parray [I];
}
}
# Region ienumerable <person> Members
Public ienumerator <person> getenumerator ()
{
Return this;
}
# Endregion
# Region ienumerable members
Ienumerator ienumerable. getenumerator ()
{
Return this;
}
# Endregion
# Region ienumerator <person> Members
Public Person current
{
Get
{
Try
{
Return _ people [position];
}
Catch (indexoutofrangeexception)
{
Throw new indexoutofrangeexception ();
}
}
}
# Endregion
# Region idisposable members
Public void dispose ()
{
}
# Endregion
# Region ienumerator members
Object ienumerator. Current
{
Get
{
Try
{
Return _ people [position];
}
Catch (indexoutofrangeexception)
{
Throw new indexoutofrangeexception ();
}
}
}
Public bool movenext ()
{
Position ++;
Return (position <_ people. Length );
}
Public void reset ()
{
Position =-1;
}
# Endregion
}
Then you can use foreach to access the custom set:
Person [] fig = new person [3]
{
New person ("John", "Smith "),
New person ("Jim", "Johnson "),
New person ("Sue", "rabon "),
};
People peoplelist = new people (inclulearray );
Foreach (person P in peoplelist)
Console. writeline (P. firstname + "" + P. lastname );
The following describes how to use the yield Keyword:
Note: first, it can only be used in one iterator method. That is to say, the return value type of this method can only be ienumerable, ienumerator, ienumerable <t> or ienumerator <t>. Second, it has only two syntaxes: yield return expression; or yield break;
For example, the following method uses yield return to return each value that meets the condition in the loop, but does not exit:
Public static class numberlist
{
// Create an array of integers.
Public static int [] ints = {1, 2, 3, 5, 8, 13, 21, 34,55, 89,144,233,377 };
// Define a property that returns only the even numbers.
Public static ienumerable <int> geteven ()
{
// Use yield to return the even numbers in the list.
Foreach (int I in ints)
If (I % 2 = 0)
Yield return I;
}
}
The call is as follows:
// Display the even numbers.
Console. writeline ("even numbers ");
Foreach (int I in numberlist. geteven ())
Console. writeline (I );
In this iterator loop, only yield break can be used to exit the loop (and the entire method is also exited). If break is used, it cannot be compiled. For example:
Public static ienumerable <int> geteven ()
{// Use yield to return the even numbers in the list.
Foreach (int I in ints)
If (I % 2 = 0)
Yield break;
Console. writeline ();
}
If yield break; is executed, the following console. writeline (); will not be executed. The entire method body will exit after yield break is executed.
In addition, the following method is used:
Ienumerable <int> getvalues ()
{
Yield return 1;
Yield return 2;
Yield return 3;
Yield return 4;
}
You can use
Foreach (int I in this. getvalues ())
{
Console. writeline (I );
}
For the first time, set the value of 1 for the first yield return, 2 for the second yield return, and so on.