2009-02-17 84 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