Reprinted ienumerable and ienumerator

Source: Internet
Author: User

When I was a beginner at C #, I was always confused by interfaces such as ienumerable, ienumerator, and icollection. I think it is necessary to thoroughly understand the nature of ienumerable and ienumerator.

Next we will first look at the syntax definitions of the ienumerable and ienumerator interfaces. In fact, the ienumerable interface is very simple and only contains an abstract method getenumerator (). It returns an ienumerator object that can be used to access the set cyclically. What are the ienumerator objects? It is a real set accesser. Without it, you cannot use the foreach statement to traverse the set or array, because only the ienumerator object can access items in the set, if the items in the set cannot be accessed, it is impossible to traverse the set cyclically. Let's see what the ienumerator interface defines. We know that the ienumerator interface defines a current attribute, movenext and reset methods. How simple is this. Since the ienumerator object is an accesser, there should be at least one current attribute to get the items in the current set.

The movenext method only moves the internal position of the cursor forward (that is, moving to an element). How can we avoid moving forward for loop traversal?

Detailed explanation:

Ienumerable is always associated with ienumerator and foreach.

C # supports the keyword foreach, allowing us to traverse any array content:

// Traverse array items

Int [] myarrayofints = {10, 20, 30, 40 };

Foreach (int I in my myarrayofints)

{

Console. wirteline (I );

}

Although it seems that only Arrays can use this structure, any type that supports the getenumerator () method can be computed using the foreach structure.

Public class garage
{
Car [] cararray = new car [4]; // defines a cararray of the car type in the garage. In fact, cararray is essentially an array field.

// Fill in some car objects at startup
Public garage ()
{
// Assign values to array Fields
Cararray [0] = new car ("Rusty", 30 );
Cararray [1] = new car ("clunker", 50 );
Cararray [2] = new car ("Zippy", 30 );
Cararray [3] = new car ("Fred", 45 );
}
}

Ideally, like a data value array, it is easier to use foreach to construct each subitem in an iterative garage object:

// It seems feasible.
Class Program
{
Static void main (string [] ARGs)
{
Console. writeline ("********** fun with ienumberable/ienumerator ************* \ n ");
Garage Carlot = new garage ();

// Hand over each car object in the Set
Foreach (car c in Carlot)
{
Console. writeline ("{0} is going {1} MPH", C. carname, C. currentspeed );
}

Console. Readline ();
}
}

It is frustrating that the compiler notifies us that the garage class does not implement the method named getenumerator () (apparently using foreach TraversalGarage objectIt is impossible. Because the garage class does not implement the getenumerator () method, the garage object cannot return an ienumerator object. Without the ienumerator object, it is impossible to call the movenext () method. movenext cannot be called, it is impossible to loop ). This method is defined by the ienumerable interface hidden in the system. Collections namespace. (Note,In fact, we cyclically traverse objects rather than classes, but this object is a collection object.)

Classes or structures that support such behaviors are actually sub-items declared to the caller:

// This interface informs the caller that the subitem of the object can be enumerated.

Public interface ienumerable

{

Ienumerator getenumerator ();

}

As you can see, the getenumerator method returns a reference to another interface system. Collections. ienumerator. This interface provides the infrastructure for the caller to move the internal objects contained in the ienumerable compatible container.

// This interface allows the caller to obtain a sub-item of the container

Public interface ienumerator

{

Bool movenext (); // move the internal position of the cursor forward

Object current {Get;} // get the current item (read-only attribute)

Void reset (); // reset the cursor to the front of the first member.

}

Therefore, if the garage class can also use foreach to traverse the items, we need to modify the garage type to support these interfaces and implement each method manually. However, this takes a lot of effort. Although the development of getenumerator (), movenext (), current, and reset () is no problem, there is a simpler method. Because the system. array type and many other types (such as list) have implemented the ienumerable and ienumerator interfaces, you can simply delegate requests to system. array, as shown below:

Namespace mycarienumerator
{
Public class garage: ienumerable
{
Car [] cararray = new car [4];

// Fill in some car objects at startup
Public garage ()
{
Cararray [0] = new car ("Rusty", 30 );
Cararray [1] = new car ("clunker", 50 );
Cararray [2] = new car ("Zippy", 30 );
Cararray [3] = new car ("Fred", 45 );
}
Public ienumerator getenumerator ()
{
Return this. cararray. getenumerator ();
}
}
}
// After modifying the garage type, you can use this type safely in the C # foreach structure.
// Getenumerator () is defined as public. The object user can interact with ienumerator:
Namespace mycarienumerator
{
Class Program
{
Static void main (string [] ARGs)
{
Console. writeline ("********** fun with ienumberable/ienumerator ************* \ n ");
Garage Carlot = new garage ();

// Hand over each car object in the Set
Foreach (car c in Carlot) // The reason for Traversing Carlot is because the car type is very important when Carlot. getenumerator () returns the item
{
Console. writeline ("{0} is going {1} MPH", C. carname, C. currentspeed );
}

Console. writeline ("getenumerator is defined as public, and the Object User can interact with ienumerator type. The following results are consistent with the above ");
// Manually work with ienumerator
Ienumerator I = Carlot. getenumerator ();
While (I. movenext ())
{
Car mycar = (CAR) I. Current;
Console. writeline ("{0} is going {1} MPH", mycar. carname, mycar. currentspeed );
}
Console. Readline ();
}
}
}

The following describes how to manually implement the ienumberable interface and the ienumerator interface:

Namespace foreachtestcase
{
// Inherit from the ienumerable interface, but it does not actually inherit from this interface, as long as the class contains the getenumerator () method referenced by ienumberator.
Class foreachtest: ienumerable {
Private string [] elements; // array of loaded strings
Private int CTR = 0; // subscript counter of the array

/// <Summary>
/// Initialized string
/// </Summary>
/// <Param name = "initialstrings"> </param>
Foreachtest (Params string [] initialstrings)
{
// Allocate memory space for strings
Elements = new string [8];
// Copy the string passed to the constructor
Foreach (string s in initialstrings)
{
Elements [CTR ++] = s;
}
}

/// <Summary>
/// Constructor
/// </Summary>
/// <Param name = "Source"> initialized string </param>
/// <Param name = "delimiters"> delimiter, which can be separated by one or more characters </param>
Foreachtest (string initialstrings, char [] delimiters)
{
Elements = initialstrings. Split (delimiters );
}

// Method in the implementation Interface
Public ienumerator getenumerator ()
{
Return new foreachtestenumerator (this );
}

Private class foreachtestenumerator: ienumerator
{
Private int position =-1;
Private foreachtest T;
Public foreachtestenumerator (foreachtest T)
{
This. t = T;
}

# Region Implementation Interface

Public object current
{
Get
{
Return T. elements [position];
}
}

Public bool movenext ()
{
If (position <t. elements. Length-1)
{
Position ++;
Return true;
}
Else
{
Return false;
}
}

Public void reset ()
{
Position =-1;
}

# Endregion
}
Static void main (string [] ARGs)
{
// Foreachtest F = new foreachtest ("This is a sample sentence.", new char [] {'', '-'});
Foreachtest F = new foreachtest ("this", "is", "A", "sample", "sentence .");
Foreach (string item in F)
{
System. Console. writeline (item );
}
Console. readkey ();
}
}
}

Ienumerable <t> Interface

A set of ienmerable <t> interfaces is strongly typed. It provides a safer type for the iteration of sub-objects.

Public class listboxtest: ienumerable <string>
{
Private string [] strings;
Private int CTR = 0;

# Region ienumerable <string> Member
// Enumeration can be returned for enumerated classes
Public ienumerator <string> getenumerator ()
{
Foreach (string s in strings)
{
Yield return S;
}
}

# Endregion

# Region ienumerable Member
// Explicitly implement the interface
System. Collections. ienumerator system. Collections. ienumerable. getenumerator ()
{
Return getenumerator ();
}

# Endregion

// Use a string to initialize the list box
Public listboxtest (Params string [] initialstrings)
{
// Allocate memory space for strings
Strings = new string [8];
// Copy the string passed to the constructor
Foreach (string s in initialstrings)
{
Strings [CTR ++] = s;
}
}

// Add a string at the end of the list box
Public void add (string thestring)
{
Strings [CTR] = thestring;
CTR ++;
}

// Allow array-Based Access
Public String This [int Index]
{
Get {
If (index <0 | index> = strings. length)
{
// Handle poor Indexes
}
Return strings [Index];
}
Set {
Strings [Index] = value;
}
}

// Number of released strings
Public int getnumentries ()
{
Return CTR;
}
}
Class Program
{
Static void main (string [] ARGs)
{
// Create a new list box and initialize it.
Listboxtest LBT = new listboxtest ("hello", "world ");

// Add a new string
LBT. Add ("who ");
LBT. Add ("is ");
LBT. Add ("Douglas ");
LBT. Add ("Adams ");

// Test Access
String SUBST = "Universe ";
LBT [1] = SUBST;

// Access all strings
Foreach (string s in LBT)
{
Console. writeline ("value: {0}", S );
}
Console. readkey ();
}
}

To sum up, whether a type supports foreach traversal must meet the following conditions:

Solution 1: Enable this class to implement the ienumerable Interface

Solution 2: this class has a public getenumerator instance method, and the return type includes the public bool movenext () instance method and the public current instance attribute.

Reproduced http://blog.csdn.net/byondocean/article/details/6871881

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.