2009-02-17 82 views
3

拿这里的例子:关于产品产量return语句

public static IEnumerable<BigInt> EvenNumbers(IEnumerable<BigInt> numbers) 
{ 
    foreach (BigInt number in numbers) 
    { 
     if (number % 2 == 0) 
     { 
      yield return number; 
     } 
    } 
} 

这将返回只有符合条件(N%2 == 0),它的值。但收益回报率有什么区别;并返回号码;?

如果我说yield return number,它会将每个数字返回给调用函数等吗?我在哪里可以找到关于幕后发生的一些细节?

感谢

回答

5

“回归”根本不会在这里工作(因为它会尝试返回BigInt和方法声明的IEnumerable<BigInt>。乔恩斯基特具有迭代器块的一个很好的写了(这是什么)在免费C# in Depth 6(当时买整本书 - 这真的是值得;-p)


编辑 - 这里有一个非常粗糙版本的你会做什么为了写这个你rself;注意它不完全相同,但是达到了目标。我想你会同意yield return版本更容易!

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
static class Program 
{ 
    static void Main() 
    { 
     IEnumerable<int> source = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
     foreach (int value in EvenNumbers(source)) 
     { 
      Console.WriteLine(value); 
     } 
    } 

    public static IEnumerable<int> EvenNumbers(IEnumerable<int> numbers) 
    { 
     return new EvenEnumerable(numbers); 
    } 
    class EvenEnumerable : IEnumerable<int> 
    { 
     private readonly IEnumerable<int> numbers; 
     public EvenEnumerable(IEnumerable<int> numbers) { 
      this.numbers = numbers; 
     } 
     public IEnumerator<int> GetEnumerator() 
     { 
      return new EvenEnumerator(numbers); 
     } 
     IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } 
    } 
    class EvenEnumerator : IEnumerator<int> 
    { 
     private readonly IEnumerable<int> numbers; 
     public EvenEnumerator(IEnumerable<int> numbers) 
     { 
      this.numbers = numbers; 
     } 
     private int current; 
     void IEnumerator.Reset() { throw new NotSupportedException(); } 
     public int Current { get { return current; } } 
     object IEnumerator.Current { get { return Current; } } 
     IEnumerator<int> iter; 
     public bool MoveNext() 
     { 
      if (iter == null) iter = numbers.GetEnumerator(); 
      while (iter.MoveNext()) 
      { 
       int tmp = iter.Current; 
       if (tmp % 2 == 0) 
       { 
        current = tmp; 
        return true; 
       } 
      } 
      return false; 
     } 
     public void Dispose() 
     { 
      if (iter != null) 
      { 
       iter.Dispose(); 
       iter = null; 
      } 
     } 
    } 
} 
+0

感谢您的。我读过Skeet的网站,我会通过阅读他的书来赞美这一点。应该帮助很多。 – dotnetdev 2009-02-17 23:54:47

1

使用yield return实际上会导致编译器创建一个简单的IEnumerator类来完成循环的工作。 for循环的结构实际上决定了编译器创建的MoveNext方法内部的操作。

检出this blog post样本IL解构

+0

有趣的是,我读了那个链接。我现在有了更好的理解。如果我调用一个涉及yield return(以及一个迭代器块)并返回IEnumerable的方法,则每次产生yield return时,控制都会返回给调用函数。 IEnumerable只能使用yield return吗? – dotnetdev 2009-02-18 00:09:27