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.Add(i); //这里的add就把结果都给了result,返回一个List<int>类型的result对象,因此这里返回的结果result是List<int>类型,会转化为IEnumerable<int>类型 } } return result;}
使用yeild return实现
    
    
    
    
    
static IEnumerable<int> FilterWithYield(){ foreach (int i in GetInitialData()) { if (i > 2) { yield return i; } } yield break; Console.WriteLine("这里的代码不执行");}
客户端调用的代码是相同的
    
    
    
    
    
static void Main(string[] args){ foreach (var item in FilterWithYield()) { Console.WriteLine(item); } Console.ReadKey(); }
使用这个代码测试LINQ表达式,结果发现:方法的类不是IEnumerable<T>类型,只有方法的返回值是IEnumerable<T>,因此只能对方法的返回值使用LINQ
因此使用LINQ就有两个条件:
1.对类来讲,这个类继承了IEnumerable<T>,就要实现IEnumerator GetNumerator方法
2.对方法来讲,这个方法返回了IEnumerable<T>接口的类型
虽然2种方法的输出结果是同样的,但运做过程迥然不一样。第一种方法,是把结果集所有加载到内存中再遍历;第二种方法,客户端每调用一次,yield return就返回一个值给客户端,是"按需供给"。

第一种方法,客户端调用过程大体为:spa

使用yield return,客户端调用过程大体为:.net

使用yield return为何能保证每次循环遍历的时候从前一次中止的地方开始执行呢?code

--由于,编译器会生成一个状态机来维护迭代器的状态。htm

简单地说,当但愿获取一个IEnumerable<T>类型的集合,而不想把数据一次性加载到内存,就能够考虑使用yield return实现"按需供给"。对象



实现一个IEnumerable接口的代码

    
    
    
    
    
public class Stack : IEnumerable { int[] items = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; public IEnumerator GetEnumerator() { for (int i = 0; i < items.Length; i++) { yield return items[i]; // return返回的是IEnumerator集合对象,也就是说类中自己就有了一个 //IEnumerator对象,Foreach遍历的时候,也遍历的是这个IEnumerator对象,因此直接写foreach(var i in ss)就能够了,底层帮助完成其余代码 } } }





 


相关文章
相关标签/搜索