C#高级程序设计(七)——迭代
2012-08-27 15:09
183 查看
.NET使用IEnumerator接口和IEnumerable接口(以及它们的泛型版本)实现迭代器模式,迭代是LINQ的核心。
接口定义如下:
一、C#1实现迭代方式
C#1通过实现接口实现迭代,下面是一个例子,可以指定起始的顺序来迭代集合,其中的一些注意点在注释中有所体现。
二、C#2实现迭代方式
C#2提供了yield关键字,使得迭代实现代码大大简化,下面使用yield方式来改写上面的实现。
yield 关键字向编译器指示它所在的方法是迭代器块。 编译器生成一个类来实现迭代器块中表示的行为。 在迭代器块中,yield 关键字与 return 关键字结合使用,向枚举器对象提供值。 这是一个返回值,例如,在 foreach 语句的每一次循环中返回的值。 yield 关键字也可与 break 结合使用,表示迭代结束。
三、迭代器
迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符,它使您能够在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。您只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T>
接口的相关迭代方法,进一步简化了迭代的开发。
四、迭代器实现LINQ查询
下面的例子使用迭代器实现了LINQ查询中Where方法。
接口定义如下:
public interface IEnumerable { IEnumerator GetEnumerator(); } public interface IEnumerator { object Current { get; } bool MoveNext(); void Reset(); } public interface IEnumerable<out T> : IEnumerable { IEnumerator<T> GetEnumerator(); } public interface IEnumerator<out T> : IDisposable, IEnumerator { T Current { get; } }
一、C#1实现迭代方式
C#1通过实现接口实现迭代,下面是一个例子,可以指定起始的顺序来迭代集合,其中的一些注意点在注释中有所体现。
public class IterationSample : IEnumerable<string> { string[] values; int startingPoint; public IterationSample(string[] values, int startingPoint) { this.values = values; this.startingPoint = startingPoint; } public IEnumerator<string> GetEnumerator() { // This is important to return a new instance of iterator // so that each foreach loop will have its own iterator. return new IterationSampleIterator(this); } // Class that implement IEnumerable<T> must also implement IEnumerable, // here is a workaround to implement GetEnumerator method that defined // in both IEnumerable<T> and IEnumerable. IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } // Inner class can access to private members of its parent class. class IterationSampleIterator : IEnumerator<string> { IterationSample parent; int position; internal IterationSampleIterator(IterationSample parent) { this.parent = parent; position = -1; } public bool MoveNext() { if (position != parent.values.Length) { position++; } return position < parent.values.Length; } object IEnumerator.Current { get { return Current; } } public string Current { get { if (position == -1 || position == parent.values.Length) { throw new InvalidOperationException(); } int index = position + parent.startingPoint; index = index % parent.values.Length; return parent.values[index]; } } public void Reset() { position = -1; } public void Dispose() { } } } string[] values = { "a", "b", "c", "d", "e" }; IterationSample collection = new IterationSample(values, 3); foreach (object x in collection) { Console.WriteLine(x); }
二、C#2实现迭代方式
C#2提供了yield关键字,使得迭代实现代码大大简化,下面使用yield方式来改写上面的实现。
public class IterationSample : IEnumerable<string> { string[] values; int startingPoint; public IterationSample(string[] values, int startingPoint) { this.values = values; this.startingPoint = startingPoint; } public IEnumerator<string> GetEnumerator() { for (int index = 0; index < values.Length; index++) { yield return values[(index + startingPoint) % values.Length]; } } // Class that implement IEnumerable<T> must also implement IEnumerable, // here is a workaround to implement GetEnumerator method that defined // in both IEnumerable<T> and IEnumerable. IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } string[] values = { "a", "b", "c", "d", "e" }; IterationSample collection = new IterationSample(values, 3); foreach (object x in collection) { Console.WriteLine(x); }
yield 关键字向编译器指示它所在的方法是迭代器块。 编译器生成一个类来实现迭代器块中表示的行为。 在迭代器块中,yield 关键字与 return 关键字结合使用,向枚举器对象提供值。 这是一个返回值,例如,在 foreach 语句的每一次循环中返回的值。 yield 关键字也可与 break 结合使用,表示迭代结束。
yield return <expression>; yield break;
三、迭代器
迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符,它使您能够在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。您只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T>
接口的相关迭代方法,进一步简化了迭代的开发。
public class Program { //using System.Collections; public static IEnumerable Power(int number, int exponent) { int counter = 0; int result = 1; while (counter++ < exponent) { result = result * number; yield return result; } } static void Main() { // Display powers of 2 up to the exponent 8: foreach (int i in Power(2, 8)) { Console.Write("{0} ", i); } } } /* Output: 2 4 8 16 32 64 128 256 */
四、迭代器实现LINQ查询
下面的例子使用迭代器实现了LINQ查询中Where方法。
public static IEnumerable<T> Where<T>(IEnumerable<T> source, Predicate<T> predicate) { if (source == null || predicate == null) { throw new ArgumentNullException(); } return WhereImpl(source, predicate); } private static IEnumerable<T> WhereImpl<T>(IEnumerable<T> source, Predicate<T> predicate) { foreach (T item in source) { if (predicate(item)) { yield return item; } } } ... IEnumerable<string> lines = LineReader.ReadLines("../../FakeLinq.cs"); Predicate<string> predicate = delegate(string line) { return line.StartsWith("using"); }; foreach (string line in Where(lines, predicate)) { Console.WriteLine(line); }
相关文章推荐
- javascript高级程序设计 第五章引用类型 迭代方法
- JavaScript高级程序设计--对象,数组(栈方法,队列方法,重排序方法,迭代方法)
- 深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)
- 深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)
- javascript高级程序设计-Array迭代及归并
- js高级程序设计
- javascript高级程序设计第三版 第20章 JSON
- Javascript高级程序设计第16章(HTML5脚本编程)--XDM
- JavaScript高级程序设计之基本概念之变量第3.3讲笔记
- 【JS】JavaScript高级程序设计笔记 第2章 ECMAScript基础
- JavaScript高级程序设计之基本概念之函数第3.7讲笔记
- JavaScript高级程序设计之引用类型之单体内置对象之Math对象第5.7.2讲笔记
- JavaScript高级程序设计阅读笔记(十六) javascript检测浏览器和操作系统-detect.js
- C#高级程序设计(一)——从接口到代理到匿名方法到lambda表达式
- JavaScript高级程序设计之函数表达式之闭包第7.2讲笔记
- js高级程序设计第三版 第四章
- 9.1高级特性-迭代
- C#高级程序设计(三)——泛型
- 《C#与.NET 3.0高级程序设计》第22章读书笔记
- [JavaScript高级程序设计]语法、数据类型和一些区别注意