3

私は非常に奇妙な問題に遭遇しました。次のコードは予想どおりに実行されません。

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);
    }
}

2つの質問。まず、YieldFun は、例外がスローされても引き続き動作するようです。次に、呼び出し元の try-catch ブロックが、スローされた例外をキャッチできません。

なぜこれ?これを解決する方法は?

4

2 に答える 2

6

これは、反復子の実行の遅延が原因です。あなたの例外はあなたが思っているよりも遅くスローされます:foreach (int i in result)反復してスローしようとしますが、そこで例外をキャッチしません。

関数の本体は、アイテムを反復しようとするまで実行されません。したがって、この関数を呼び出すだけでは、実際には「throw ...」ステートメントには到達しません。結果を手動で反復して、例外がスローされた正確な時点を確認できます。

于 2012-09-05T01:18:05.050 に答える
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 のため)...catch が呼び出され、result設定されないため、for ループが結果を反復しようとすると... be null....null チェックを追加する必要があります。

于 2012-09-05T01:34:13.277 に答える