收益率和尝试捕获量。(C#)

时间:2012-09-05 01:14:10

标签: c# return try-catch yield

我遇到了一个非常奇怪的问题。以下代码无法运行。

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块无法捕获抛出的异常。

为什么这样?以及如何解决这个问题?

2 个答案:

答案 0 :(得分:6)

这是由迭代器的延迟执行引起的。您的异常比您想象的要晚一些:foreach (int i in result)尝试迭代并抛出,但是您不会在那里捕获异常。

在尝试迭代项目之前,不会执行函数体。所以只是调用这个函数实际上并没有达到“throw ...”语句。您可以手动迭代结果以查看抛出异常的确切位置。

答案 1 :(得分: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 ....你需要添加一个空检查。