2012-09-05 57 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 ....您需要添加空检查。

相关问题