2012-05-17 21 views
7

私は次のコードをお持ちの場合:リストに例外がスローされた場合<T> .ForEach、反復は停止しますか?

List<MyClass> list = GetList(); 
list.ForEach(i => i.SomeMethod()); 

をしてのは、SomeMethod()が例外をスローしましょう。 ForEachは反復し続けますか、それともちょうどそこで停止しますか?

終了する場合は、メソッドを実行するためにコレクション内の残りのアイテムを取得する方法はありますか?

答えて

13

はい、例外がスローされると、ループは終了します。その振る舞いを望まない場合は、例外処理をデリゲートに配置する必要があります。あなたは簡単にこのためのラッパーメソッドを作成することができます。

public static Action<T> SuppressExceptions<T>(Action<T> action) 
{ 
    return item => 
    { 
     try 
     { 
      action(item); 
     } 
     catch (Exception e) 
     { 
      // Log it, presumably 
     } 
    }; 
} 

は正直に言うと、私は可能であればこれを避けるためにをしようとするだろう。 すべて例外をキャッチするのは不愉快です。また、失敗したアイテムや例外などは記録されません。あなたは本当にあなたの必要条件をより詳細に考える必要があります。

  • 失敗したアイテムを収集する必要がありますか?
  • 例外を収集する必要がありますか?
  • キャッチしたい例外はありますか?

通常のforeachループを代わりに使用し、エラーを処理し、エラーが発生したときに収集する別の方法を作成することは、ほぼ確実にクリーンです。個人的には、foreachForEach以上に使用することをお勧めします。Eric Lippert's thoughts on this tooをお読みください。

+0

私は質問タイトルを更新しました。ありがとうございましたjon – Jason

+0

@ Jason:Righto - その最初の文を取り除きます。私の答えを編集しました... –

+0

この有益な、非常に有益な答えを考えてくれてありがとう。 – Jason

3

エラーが発生します。また、foreachを再実装する途中です。方法については、ちょうど:

foreach (var item in list) 
{ 
    try 
    { 
     // dangerous thing with item 
    } 
    catch (Exception e) 
    { 
     // how do you want to log this? 
    } 
} 

これはほとんどのバージョンの.NETで動作し、明らかに副作用があるという利点があります。もちろん、このコードを直接ForEachデリゲートに配置することはできますが、ラムダ関数ではなくメソッド自体になる場合は、それだけを提案します。

public static IEnumerable<Tuple<T,Exception>> ForEachWithCatch<T>(this IEnumerable<T> items, Action<T> action) 
{ 
    var exceptions = new List<Tuple<T,Exception>>(); 

    foreach(var item in items) 
    { 
     try 
     { 
      action(item); 
     } 
     catch(Exception e) 
     { 
      exceptions.Add(Tuple.Create(item, e)); 
     } 
    } 

    return exceptions; 
} 

これは失敗した各項目の列挙を送り返し、それが対応だ:


合理的な代替は、すべての例外を捕捉し、呼び出し元に戻ってそれらを送信し、独自のForEachWithCatch拡張機能を作成することです例外。

0

あなたSomeMethodは、try-catchブロックを実装している場合は、foreachのは

void SomeMethod() 
{ 
    try 
    { 
    //Some operation on i 
    } 
    catch(Exception ex) 
    { 
    } 
} 

を継続していきます。しかしいない場合、その後のforeachが解除されます。

一つ、それをすることの何があなたのコード内でゼロのtry-catchブロックを持っているこのよう

list.ForEach(i => 
    { 
     try 
     { 
      i.SomeMethod(); 
     } 
     catch(Exception ex) 
     { 
     } 
    }); 

しかし、その常に良いです。そうでなければ、犯人がどこにいるのかは決して分かりません。

関連する問題