Visual CSharp 1002005 A Developers Notebook [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Visual CSharp 1002005 A Developers Notebook [Electronic resources] - نسخه متنی

Jesse Liberty

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید









1.4. Enumerate Using Generic Iterators



In the previous examples you could not
iterate over your list of
Pilgrims using a foreach loop.
As such, if you try to use the following code in Example 1-3:


foreach ( Pilgrim p in pilgrims )
{
Console.WriteLine("The pilgrim's name is " + p.ToString( ));
}


you will receive the following error:


Error      1      foreach statement cannot operate 
on variables of type
'ImplementingGenericInterfaces.LinkedList
<ImplementingGenericInterfaces.Pilgrim>'
because 'ImplementingGenericInterfaces.LinkedList
<ImplementingGenericInterfaces.
Pilgrim>' does not contain a public
definition for 'GetEnumerator'


In earlier versions of C#, implementing
GetEnumerator was somewhat complicated and always
tedious, but in C# 2.0 it is greatly simplified.


Note: Adding iterators allows a client to iterate over your class
using foreach.

1.4.1. How do I do that?



To simplify the process of creating iterators, we'll
begin by simplifying both the Pilgrim class and
the Linked List class. The Linked
List
class will forgo all use of nodes and will store its
contents in a fixed-size array (as the simplest type-safe container
imaginable). Thus, it is a Linked List in name
only! This will allow us to focus on the implementation of the
IEnumerator interface, as shown in Example 1-4.



Example 1-4. Implementing IEnumerator, simplified


#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
#endregion
namespace SimplifiedEnumerator
{
// simplified Pilgrim
public class Pilgrim
{
private string name;
public Pilgrim(string name)
{
this.name = name;
}
public override string ToString( )
{
return this.name;
}
}
// simplified Linked List
class NotReallyALinkedList<T> : IEnumerable<T>
{
// the entire linked list is stored in this
// fixed size array
T[ ] myArray;
// constructor takes an array and stores the members
public NotReallyALinkedList(T[ ] members)
{
myArray = members;
}
// implement the method for IEnumerable
IEnumerator<T> IEnumerable<T>.GetEnumerator( )
{
foreach (T t in this.myArray)
{
yield return t;
}
}
System.Collections.IEnumerator System
.Collections.IEnumerable.GetEnumerator( )
{
throw new NotImplementedException( );
}
}
class Program
{
static void Main(string[ ] args)
{
// hardcode a string array of Pilgrim objects
Pilgrim[ ] pilgrims = new Pilgrim[5];
pilgrims[0] = new Pilgrim("The Knight");
pilgrims[1] = new Pilgrim("The Miller");
pilgrims[2] = new Pilgrim("The Reeve");
pilgrims[3] = new Pilgrim("The Cook");
pilgrims[4] = new Pilgrim("The Man Of Law");
// create the linked list, pass in the array
NotReallyALinkedList<Pilgrim> pilgrimCollection =
new NotReallyALinkedList<Pilgrim>(pilgrims);
// iterate through the linked list
foreach (Pilgrim p in pilgrimCollection)
{
Console.WriteLine(p);
}
}
}
}


Output:


The Knight
The Miller
The Reeve
The Cook
The Man Of Law



1.4.2. What just happened?



In this example, the linked list is greatly simplified to keep its
members in an array (in fact, it is not really a linked list at all).
Because you've made your
pseudo-LinkedList enumerable, however, now you can
enumerate the Pilgrims in the
pilgrims collection using a
foreach loop.


When you write:


foreach (Pilgrim p in pilgrimCollection)


the C# compiler invokes the GetEnumerator method
of the class. Internally, it looks more or less like this:


Enumerator e = pilgrimCollection.GetEnumerator( );
while (e.MoveNext( ))
{
Pilgrim p = e.Current;
}


As noted earlier, in C# 2.0 you do not have to worry about
implementing MoveNext( ) or the current property.
You need only use the new C# keyword
yield.


Note: Whenever you call foreach, the compiler internally
translates it to a call to GetEnumerator.You use yield only in iterator blocks. It either
provides a value to the enumerator object or it signals the end of
the iteration:

yield return expression;
yield break;


If you step into the foreach loop with the
debugger, you'll find that each time through the
foreach loop, the GetEnumerator
method of the linked list is called, and each time through the next
member in the array, it is yielded back to the calling
foreach loop.



1.4.3. What about...



...implementing the GetEnumerator method on a more
complex data structure, such as our original
LinkedList?


That is shown in the next lab.



1.4.4. Where can I learn more?



For more on this
subject, see the extensive
article in MSDN titled
"Iterators (C#)."



/ 71