12.C#yield return和yield break及实际应用小例(六章6.2-6.4)

  晚上好,各位。今天结合书中所讲和MSDN所查,聊下yield关键字,它是我们简化迭代器的关键。

  如果你在语句中使用了yield关键字,则意味着它在其中出现的方法、运算符或get访问器是迭代器,通过使用yield定义迭代器,可在实现自定义集合类型的IEnumerable和IEnumerator模式时无需显示类(保留枚举状态类),使用yield有两种形式,如下

1 yield return 表达式
2 yield break

  先说明一下yield return语句,每一次返回一个元素。通过foreach语句或LINQ查询来使用迭代器方法。foreach循环的每次迭代都会调用迭代器方法,会保存当前返回的状态。

 1 static void Main(string[] args)
 2 {
 3     foreach (int i in GetValues())
 4     {
 5         Console.WriteLine(i);
 6     }
 7     Console.ReadKey();
 8 }
 9
10 static IEnumerable<int> GetValues()
11 {
12     yield return 1;
13     yield return 2;
14     yield return 3;
15 }

  不能将yield return语句放在try-catch之中,但可以把它放在try-finally之中。yield return有两个特点:1.返回类型必须是IEnumerable、IEnumerator、IEnumerator<T>、IEnumerable<T>.2.不能使用ref和out修饰符。在匿名方法和不安全代码中不能包含yield return和yield break。下面我们使用yield return来简化上一篇中对Student的迭代,重新个性了Queue<T>这个泛型类,如下

 1 class Queue<T> : IEnumerable<T> where T : class
 2 {
 3     public List<T> objects = new List<T>();
 4     int startPoint = 0;
 5     public Queue(List<T> list)
 6     {
 7         objects = list;
 8     }
 9
10     //实现从IEnumerable中的GetEnumerator方法
11     /*
12         个人觉得这个方法在迭代中只会调用一次,不然每次都返回一个新的QueueIterator<T>对象,位置记录都会重置为-1
13     */
14     public IEnumerator<T> GetEnumerator()
15     {
16         //return new QueueIterator<T>(this);
17         for (int index = 0; index < objects.Count; index++)
18         {
19
20             yield return objects[(index + startPoint) % objects.Count];
21         }
22     }
23
24     IEnumerator IEnumerable.GetEnumerator()
25     {
26         throw new NotImplementedException();
27     }
28 }

  代码到了yield return时,返回objects中一个合适的元素,并保存当前的状态,等下一次调用时从记数的位置开始。在使用程序中,如下,和原先一样。

 1 List<Student> list = new List<Student> {
 2     new Student("СA"),
 3     new Student("СB"),
 4     new Student("СC"),
 5     new Student("СD"),
 6     new Student("СE")
 7 };
 8 ConsoleDemo.Chapter6.Queue<Student> lq = new Chapter6.Queue<Student>(list);
 9
10 foreach (var obj in lq)
11 {
12     obj.SayName();
13 }

  可以看到结果都是迭代的打印每一个元素的名字。在来说下return break,从break中可以看中,是跳出,那意思就应该上跳出迭代,如

 1 class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5
 6         foreach (int i in GetValues())
 7         {
 8             Console.WriteLine(i);
 9         }
10         Console.ReadKey();
11     }
12
13     static IEnumerable<int> GetValues()
14     {
15         yield return 1;
16         yield return 2;
17         yield break;
18         yield return 3;
19     }
20 }

  到了yield return 2时,下一语句是yield break,则在控制台只会打印1,2,因为在打印3之前就使用yield break跳出迭代了。

  下面我们使用一个实际点的读文件的例子。新建一个文本demo.txt,内容如下

 1 1
 2 2
 3 3
 4 4
 5 5
 6 6
 7 7
 8 8
 9 9
10 0

  代码如下

 1 class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5         foreach(var line in ReadLines("./demo.txt"))
 6         {
 7             Console.WriteLine(line);
 8         }
 9         Console.ReadKey();
10     }
11
12     static IEnumerable<string> ReadLines(string path)
13     {
14         string line;
15         TextReader tr = File.OpenText(path);
16         while ((line = tr.ReadLine()) != null)
17         {
18             yield return line;
19         }
20     }
21 }

  当然其实File中的表态方法是有ReadLines方法的,返回的也是IEnumerable<string>,看来我们是多此一举了,不过也不错,知道了一些yield的使用,原理的那些真心不敢写,写了自己也看不懂,希望以后能用自己组织语言,解译那些原理。

  请斧正。

时间: 2024-12-19 17:19:45

12.C#yield return和yield break及实际应用小例(六章6.2-6.4)的相关文章

yield return 和 yield break

//yield return 返回类型必须为 IEnumerable.IEnumerable<T>.IEnumerator 或 IEnumerator<T>. static IEnumerator<int> yieldTest() //yield return 返回IEnumerator  { yield return 1; yield return 4; if (true)//如果为True 输出 1,4;//如果是False 输出 1,4,3,2 { yield b

yield return,yield break

转自, http://www.cnblogs.com/kingcat/archive/2012/07/11/2585943.html yield return 表示在迭代中下一个迭代时返回的数据,除此之外还有yield break, 其表示跳出迭代,为了理解二者的区别我们看下面的例子 class A : IEnumerable{    private int[] array = new int[10]; public IEnumerator GetEnumerator()    {       

C# yield return用法

本文实例讲述了C#中yield return用法,并且对比了使用yield return与不使用yield return的情况,以便读者更好的进行理解.具体如下: yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历. 有这样的一个int类型的集合: ? 1 2 3 4 static List<int> GetInitialData() {   return new List<int>(){

C#中的yield return与Unity中的Coroutine(协程)

C#中的yield return C#语法中有个特别的关键字yield, 它是干什么用的呢? 来看看专业的解释: yield 是在迭代器块中用于向枚举数对象提供值或发出迭代结束信号.它的形式为下列之一:yield return <expression>;yield break 看如下例子: 1 public class CustomCollection :IEnumerable { 2 3 public static void Main (string[] args) 4 { 5 Custom

C#中yield return用法分析(转载自shichen2014)

本文实例讲述了C#中yield return用法,并且对比了使用yield return与不使用yield return的情况,以便读者更好的进行理解.具体如下: yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历. 有这样的一个int类型的集合: ? 1 2 3 4 static List<int> GetInitialData() {   return new List<int>(){

造轮子_C#中yield return用法分析

厂址: http://www.jb51.net/article/54810.htm static List<int> GetInitialData() {   return new List<int>(){1,2,3,4}; } 打印出所有值大于2的元素 不使用yield return的实现 static IEnumerable<int> FilterWithoutYield() {   List<int> result = new List<int&

C#中,什么时候用yield return

yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历. 有这样的一个int类型的集合: static List<int> GetInitialData() { return new List<int>(){1,2,3,4}; } 需要打印出所有值大于2的元素. 不使用yield return的实现 static IEnumerable<int> FilterWithoutYiel

.net yield return

yield在迭代器块中用于向枚举数对象提供值或发出迭代结束信号.它的形式为下列之一: yield return <expression>; yield break; 计算表达式并以枚举数对象值的形式返回:expression 必须可以隐式转换为迭代器的 yield 类型. yield 语句只能出现在 iterator 块中,该块可用作方法.运算符或访问器的体.这类方法.运算符或访问器的体受以下约束的控制: l 不允许不安全块. l 方法.运算符或访问器的参数不能是 ref 或 out. yie

C#中yield return用法

1.yield关键字用于遍历循环中,yield return用于返回IEnumerable<T>,yield break用于终止循环遍历 不使用yield return的实现 static IEnumerable<int> FilterWithoutYield() { List<int> result = new List<int>(); foreach (int i in GetInitialData()) { if (i > 2) { result