20

特定のメソッドを呼び出して何らかの作業を行いたいだけで、スローされる可能性のある特定の例外をすべて処理する必要がない特定のシナリオがあります。代わりに、私が本当に気にしているのは、メソッドが成功したかどうかだけです。

.NET / C# の例を提供します。コピーしたいファイルがあり、本当に気にしているのはコピー操作が成功したかどうかだけだとしましょう。コピーが失敗した場合、特定の例外が FileNotFoundException または IOException の「十分なディスク容量がありません」例外であるかどうかは気にしません...この操作は重要ではないため、その場合、アプリケーションは通常どおりに続行します。

したがって、これを実装する方法は次のとおりです。

try 
{
  // try 
  System.IO.File.Copy(strFile, strFile + ".new");
} 
catch (Exception ex) 
{
  // if critical exception then rethrow
  if (IsCritical(ex)) 
      throw;

  // else just log and swallow...
  Console.WriteLine("Failed to copy the file: " + ex.Message);
}

ここで IsCritical(Exception ex) は次のように定義されたヘルパー メソッドです。

public static bool IsCritical(Exception ex) 
{
  if (ex is OutOfMemoryException) return true;
  if (ex is AppDomainUnloadedException) return true;
  if (ex is BadImageFormatException) return true;
  if (ex is CannotUnloadAppDomainException) return true;
  if (ex is ExecutionEngineException) return true;
  if (ex is InvalidProgramException) return true;
  if (ex is System.Threading.ThreadAbortException) 
      return true;
  return false;
}

この質問は次の記事に基づいています: 「処理できない例外をキャッチしない」ルールを念頭に置いた C# での例外処理

アイデアは、例外処理のベスト プラクティスの主なルールに従うことです。ログに記録し、アプリケーション ロジックを続行します)。

それで、これは与えられたシナリオにとって良いアプローチですか?そうでない場合、なぜ、そして何をするのがより良いでしょうか?

4

7 に答える 7

22

例外を飲み込まないようにすることが一般的に推奨される理由は、バグを隠すことができるからです。たとえば、 を実行する以外のことを行っているとします。File.Copy文字列処理も実行しています ( strFile + ".new")。これはスローできません (OOM を除く) が、計算がより複雑な場合はバグを隠していた可能性があります

この場合、すべての計算を try ブロックの外に移動する必要があります。次に、例外を飲み込んでも問題ありません。注意を払っても間違いを犯した場合に備えて、ログに記録する習慣があります。

不必要に鵜呑みにしないというルールは、開発者を自身の誤りから守るためにあります。すべてが問題ないと合理的に確信している場合は、ルールに従う必要はありません。

于 2013-11-11T10:15:02.053 に答える
6

特定のケースで特定の例外を飲み込むことは問題ありませんが、実際にはユース ケースに依存します。

例外を処理することをお勧めします。未処理の例外に対して AppDomain.UnhandledExceptionイベント処理して使用し、何が起こったかをユーザーに通知できます。

デバッグの観点からは、Visual Studio ですべての一般的なランタイム例外を中断できるため、コードにアクセスできる限り、それほど重要ではありません。(デバッグ -> 例外 -> 共通言語ランタイム例外 -> 左のチェックボックスをチェック)

リストが完全かどうかは本当にわからないので、私は重大な例外のリストに依存することは決してありません。

于 2013-11-11T11:01:30.607 に答える
0

私はあなたがあなた自身の質問に答えたと思います。ビジネスロジックに完全に依存します。しかし、一般的に、例外を「飲み込む」場合は、特定のタイプだけで、別の方法で行います。

于 2013-11-11T10:29:43.047 に答える
0

同じ try に対していくつかの catch ステートメントを追加できます。

try
{
 //code here
}
 catch (FileNotFoundException ex1) 
{
  //Do whatever you want
}
catch (IOException ex2)
{
  //Do whatever you want
}

重要とは見なさない例外を処理し、残りのすべての例外を1つだけ処理することをお勧めしますcatch (Exception er){throw ;}

また、この 2 つの特定の例外についてはIOException、をキャッチするだけで十分です。IOExceptionFileNotFountException

于 2013-11-11T10:18:30.460 に答える
0

自分で書いていないコードから発生する例外は、重大な例外として扱う必要があると言いたいです。エラーをスローしたシステムが未定義の状態にある可能性があり、したがって、その後の操作がすべて失敗する可能性があるためです。そのシステムでの試行が成功する保証はありません。

したがって、私はおそらく次のようなことをします:

  try 
    {
      System.IO.File.Copy(strFile, strFile + ".new");
     //MyLibrary throws exception clases I defined so I know what they are all about
      MyLibrary.SomeClass.DoSomething(strFile);
    }
    catch(ExceptionTypeIDefinedInMyLibraryWhichIKnowICanSafelyIgnore iex)
    {
      Console.WriteLine("Not to worry: "+ iex.Message);
    }
    catch (Exception ex) 
    {
      //This absolute is not something I can handle. Log it and throw.
      Log(ex); throw;
    }

このようにして、重大な例外を無視することはできず、サブシステムがスローするものを制御しているため、独自のサブシステムから特定のタイプの例外のみをスローできます。

ただし、実際に示したパターンに従いたい場合は、これを好転させ、処理できることがわかっている例外のみを処理し、それ以外はすべてスローする傾向があります。

そうすれば、新しいOhMyGodThereAreZombiesInTheServer例外が BCL に追加されたときに火傷を負うことはありません。

すなわち

try 
{
  // try 
  System.IO.File.Copy(strFile, strFile + ".new");
} 
catch (Exception ex) 
{
  // if critical exception then rethrow
  if (ICanHandleThis(ex)) 
  {
   Console.WriteLine("Failed to copy the file: " + ex.Message);
  }
  else
  {
   //step aside and let Dr McNinja deal with it
   throw;
  }     
}

public static bool ICanHandleThis(Exception ex) 
{
 //I don't care about these exceptions, they aren't critical
 //to my application for some reason.
 return (ex is SomeTrivialExceptionTypeIDontCareAbout 
        || ex is SomeOtherIgnorableExceptionType);

}
于 2013-11-12T11:55:02.767 に答える