2012-09-05 53 views
3

我遇到了一個很奇怪的問題。以下代碼不能運行。yield return and try-catch。(C#)

static IEnumerable<int> YieldFun() 
{ 
    int[] numbers = new int[3] { 1, 2, 3 }; 

    if(numbers.Count()==3) 
     throw new Exception("Test..."); 

    //This code continues even an exception was thrown above. 
    foreach(int i in numbers) 
    { 
     if(i%2==1) 
      yield return numbers[i]; 
    } 
} 

static void Main(string[] args) 
{ 
    IEnumerable<int> result = null; 
    try 
    { 
     result = YieldFun(); 
    } 
    catch (System.Exception ex) //Cannot catch the exception 
    { 
     Console.WriteLine(ex.Message); 
    } 


    foreach (int i in result) 
    { 
     Console.Write(" " + i); 
    } 
} 

兩個問題。 首先,即使拋出異常,YieldFun似乎仍能繼續工作。 其次,調用者的try-catch塊無法捕獲拋出的異常。

這是爲什麼?以及如何解決這個問題?

回答

6

這是由迭代器延遲執行引起的。你的異常拋出的時間比你想象的要多:foreach (int i in result)試圖迭代和拋出,但你不會在那裏發現異常。

直到嘗試迭代項目時纔會執行該函數的主體。所以只是調用這個函數實際上並沒有達到「throw ...」語句。您可以手動迭代結果以查看引發異常的確切點。

3

您可以這樣做來分離出延遲部分(包含yield的作用域會導致迭代器的構建)......並在分配發生時執行您的檢查。

static IEnumerable<int> YieldFun() 
{ 
    int[] numbers = new int[3] { 1, 2, 3 }; 

    if (numbers.Count() == 3) 
     throw new Exception("Test..."); 

    return YieldFunImpl(numbers); 
} 

static IEnumerable<int> YieldFunImpl(int []numbers) 
{ 
    //This code continues even an exception was thrown above. 
    foreach (int i in numbers) 
    { 
     if (i % 2 == 1) 
      yield return numbers[i]; 
    } 
} 

static void Main(string[] args) 
{ 
    IEnumerable<int> result = null; 
    try 
    { 
     result = YieldFun(); 
    } 
    catch (System.Exception ex) //Cannot catch the exception 
    { 
     Console.WriteLine(ex.Message); 
    } 

    if (result != null) 
    { 
     foreach (int i in result) 
     { 
      Console.Write(" " + i); 
     } 
    } 
} 

}

當異常熄滅(因爲你的COUNT()== 3)......你釣到的魚就會被調用,您result將不會設置....所以當for循環嘗試迭代結果...它將是null ....您需要添加空檢查。

相關問題