C# yield operator
Prior to .NET 2.0, the only way you could create your own collection which could be traversed using the 'foreach' construct was by having you class implementing the IEnumerable and IEnumerator Interfaces.
However since .NET 2.0 we have a new operator called 'yield'. This allows your class to be iterated by its consumer but without the need to implement the above-mentioned interfaces.
Let us see a small example of how this works:
// Our class does not implement any interface ! public class School { // Explicit
initialization just for demo purposes ! private string[] studentNames = {"John",
"Joan","Joanne", "Tony", "Peter"};
// The iterating
method public
IEnumerator GetEnumerator() { foreach
(string name in
studentNames) { // yield
return in action ! yield
return name; } } } And now the code for the consumer:
class Program { static void Main(string[]
args) { School NorthCoast = new School(); // How
School's internal collection was iterated is hidden to the user foreach
(string student in
NorthCoast) { Console.WriteLine(student); } Console.ReadLine(); } }
As you can see it is easy to make your class iteratable without having to make it implmenet any interfaces.
The following is another example (inspired by an e-mail sent to me by one of the readers of this blog!):
using System; using
System.Collections.Generic; using
System.Linq; using
System.Text; using System.IO;
namespace
ConsoleApplication4 { class Program { static void Main(string[]
args) { MyYieldFileReader
myYieldFileReader = new MyYieldFileReader(); foreach
(string line in
myYieldFileReader.ReadLine(@"C:\BuonVoyage.txt")) { Console.WriteLine(line); } Console.ReadLine(); } }
class MyYieldFileReader { public
IEnumerable ReadLine(string fileName) { using
(StreamReader tr = new
StreamReader(fileName)) { while
(!tr.EndOfStream) { yield
return tr.ReadLine(); } } } } } Finally, beware of the following constaints on the use of the 'yield' operator, as described in MSDN:
The yield statement can only appear inside an iterator block, which might be used as a body of a method, operator, or accessor. The body of such methods, operators, or accessors is controlled by the following restrictions:
Unsafe blocks are not allowed.
Parameters to the method, operator, or accessor cannot be ref or out.
A yield statement cannot appear in an anonymous method. For more information, see Anonymous Methods (C# Programming Guide).
When used with expression, a yield return statement cannot appear in a catch block or in a try block that has one or more catch clauses. For more information, see Exception Handling Statements (C# Reference).
|