1. The collection wants to support the foreach traversal, need to return an iterator (IEnumerator), and foreach will automatically invoke the iterator's State Migration (MoveNext (), curent, Reset ())
#regionAssembly mscorlib.dll, v4.0.0.0//C:\Program Files (x86) \reference Assemblies\microsoft\framework\. Netframework\v4.5\mscorlib.dll#endregionusingSystem;usingSystem.Runtime.InteropServices;namespacesystem.collections{//Summary://Supports A simple iteration over a nongeneric collection.[ComVisible (true)] [Guid ("496b0abf-cdee-11d3-88e8-00902754c43a")] Public InterfaceIEnumerator {ObjectCurrent {Get; } BOOLMoveNext (); voidReset (); }}
2.IEnumerable interface to customize the requirements of foreach
#regionAssembly mscorlib.dll, v4.0.0.0//C:\Program Files (x86) \reference Assemblies\microsoft\framework\. Netframework\v4.5\mscorlib.dll#endregionusingSystem.Runtime.InteropServices;namespacesystem.collections{//Summary://exposes the enumerator, which supports a simple iteration over a non-generic//collection.[ComVisible (true)] [Guid ("496b0abe-cdee-11d3-88e8-00902754c43a")] Public InterfaceIEnumerable {[DispID (-4)] IEnumerator GetEnumerator (); }}
3. List-like lists are defined as follows:
/// <summary> ///List/// </summary> classMylist:arraylist, ienumerable<Object> { //The iterator returns Publicienumerator<Object>GetEnumerator () {return NewMylistenumerator ( This); } /// <summary> ///1. Since IEnumerable<T>inherit from IEnumerable, so you must implement its method///2. Because a method with the same name already exists, you need to display the implementation/// </summary> /// <returns></returns>IEnumerator Ienumerable.getenumerator () {//return GetEnumerator ();//IEnumerator is the base class of ienumerator<t> return NULL; } } /// <summary> ///A custom iterator for a list/// </summary> classmylistenumerator:ienumerator<Object> { Private intCurrent =-1; PrivateMyList _mylist; Publicmylistenumerator (MyList MyList) {_mylist=MyList; Current= _mylist = =NULL|| _mylist. Count = =0? -1:0; } Public BOOLMoveNext () { current++; return_mylist! =NULL&& _mylist. Count >Current ; } Objectienumerator<Object>. Current {Get { if(_mylist! =NULL&& _mylist. Count > Current)return_mylist[current]; return NULL; } } //1. Since Ienumerable<out T> inherits from IEnumerable, its methods must be implemented//2. Because a method with the same name already exists, you need to display the implementation ObjectIEnumerator.Current {Get { //if (_mylist! = null && _mylist. Count > Current) return _mylist[current]; return NULL; } } Public voidReset () { current= _mylist = =NULL|| _mylist. Count = =0? -1:0; } //Ienumerator<t> inherits the IDisposable, so the method needs to be implemented in order to clean up the state after the Traverse is completed.//This method is automatically called after the Foreach loop is complete Public voidDispose () {}}
4.IEnumerator as an iterator, derived from the underlying programming language pointers;
An important feature of a reference type that differs from a value type is that it is used only when the real processing is performed ;
. NET in the yield keyword is very good support, the following examples illustrate:
Static voidMain (string[] args) { varList = Getstrings (5); foreach(varIteminchlist) {Console.WriteLine (item); } list= Getstrings (Ten); foreach(varIteminchlist) {Console.WriteLine (item); } console.readline (); }
Operation Result:
/// <summary> ///1.yield return puts the results of a single operation into the IEnumerable collection///2.yield Break breaks the scope of the current iterator/// </summary> /// <param name= "Length" ></param> /// <returns></returns> Public Staticienumerable<string> getstrings (intLength =0) { for(inti =0; i < length; i++) { if(I <5) { yield return string. Format ("First {0} calls", i); } Else { yield Break; }} Console.WriteLine ("code within the iteration scope after yield break is no longer executed"); }
Add: The above getstrings traditionally many people are accustomed to the following wording, but the time spent in doing so is n*m, where n is the length of the list to be calculated, and M is the first traversal length, which is why the above emphasis on the use of the time will be real processing
Public Staticlist<string> getstrings (intLength =0) { varresult =Newlist<string>(); for(inti =0; i < length; i++) { if(I <5) {result. ADD (string. Format ("First {0} calls", i)); } } returnresult; }
IEnumerable Practical Application