違いは何ですか
try { ... }
catch{ throw }
そして
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
2番目がメッセージを示しているかどうかに関係なく?
違いは何ですか
try { ... }
catch{ throw }
そして
try{ ... }
catch(Exception e) {throw new Exception(e.message) }
2番目がメッセージを示しているかどうかに関係なく?
回答:
throw; 元の例外を再スローし、元のスタックトレースを保持します。
throw ex;元の例外をスローしますが、スタックトレースをリセットし、catchブロックまでのすべてのスタックトレース情報を破棄します。
throw ex;throw new Exception(ex.Message);さらに悪い。新しいExceptionインスタンスが作成され、例外の元のスタックトレースとそのタイプが失われます。(例:)IOException。
さらに、一部の例外には追加情報が含まれます(例:)ArgumentException.ParamName。
throw new Exception(ex.Message); この情報も破壊されます。
場合によっては、すべての例外をカスタム例外オブジェクトにラップして、例外がスローされたときにコードが実行していたことに関する追加情報を提供することができます。
これを行うには、継承はという新しいクラスを定義しException、すべての4つの例外コンストラクタを追加し、必要に応じて取る追加コンストラクタInnerExceptionだけでなく、付加的な情報を、そして、新しい例外クラスをスロー渡すexとInnerException、パラメータ。元のを渡すと、InnerExceptionスタックトレースを含む元の例外のプロパティがすべて保持されます。
throw new MyCustomException(myMessage, ex);もちろんあるはずですが。
ex.Messageている、であるより悪いです。
[Serializable()]ます。
throw;例外が発生した実際の行番号がの行番号に置き換えられthrow;ます。それをどのように扱うことをお勧めしますか? stackoverflow.com/questions/2493779/...
1つ目は、元のスタックトレースを保持します。
try { ... }
catch
{
// Do something.
throw;
}
2番目の方法では、例外のタイプやメッセージ、その他のデータを変更できます。
try { ... } catch (Exception e)
{
throw new BarException("Something broke!");
}
内部例外を渡す3番目の方法もあります。
try { ... }
catch (FooException e) {
throw new BarException("foo", e);
}
私は以下を使用することをお勧めします:
他の人が見たことがないもう1つのポイント:
catch {}ブロックで何もしない場合、try ... catchを実行しても意味がありません。私はいつもこれを見ています:
try
{
//Code here
}
catch
{
throw;
}
またはさらに悪い:
try
{
//Code here
}
catch(Exception ex)
{
throw ex;
}
最悪:
try
{
//Code here
}
catch(Exception ex)
{
throw new System.Exception(ex.Message);
}
新しい例外をスローすると、現在のスタックトレースが吹き飛ばされます。
throw;元のスタックトレースを保持し、ほとんどの場合より便利です。そのルールの例外は、独自のカスタム例外に例外をラップする場合です。次に行う必要があります:
catch(Exception e)
{
throw new CustomException(customMessage, e);
}
2番目の例では、例外のスタックトレースをリセットします。1つ目は、例外の原因を最も正確に保持します。また、実際に何がうまくいかなかったかを知る上で重要な元のタイプのラップを解除しました...機能に2番目が必要な場合-たとえば、拡張情報を追加したり、カスタムの「HandleableException」などの特別なタイプで再ラップしたりすると、 InnerExceptionプロパティも設定されていることを確認してください。
最も重要な違いは、2番目の式が例外のタイプを消去することです。また、例外タイプは例外の捕捉に重要な役割を果たします。
public void MyMethod ()
{
// both can throw IOException
try { foo(); } catch { throw; }
try { bar(); } catch(E) {throw new Exception(E.message); }
}
(...)
try {
MyMethod ();
} catch (IOException ex) {
Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
Console.WriteLine ("Other error"); // [2]
}
foo()throwsの場合IOException、[1]catchブロックは例外をキャッチします。しかしbar()投げるときIOException、それは普通のExceptionアリに変換され、[1]catchブロックによってキャッチされません。
throwまたはthrow ex。どちらも例外をスローまたは再スローするために使用されます。エラー情報をログに記録するだけで、呼び出し元に情報を送り返さない場合は、catch and leaveでエラーをログに記録するだけです。ただし、例外に関する意味のある情報を、throwまたはthrow exを使用する呼び出し元に送信する場合は、これで、throwとthrow exの違いは、throwがスタックトレースとその他の情報を保持することですが、throw exは新しい例外オブジェクトを作成するため、元のスタックトレースが失われます。したがって、throwとthrow eを使用する必要があるのはいつですか。コールスタック情報をリセットするなど、例外を再スローしたい場合がまだいくつかあります。たとえば、メソッドがライブラリ内にあり、ライブラリの詳細を呼び出しコードから非表示にしたい場合、ライブラリ内のプライベートメソッドに関する情報をコールスタックに含める必要はありません。その場合、ライブラリのパブリックメソッドで例外をキャッチし、それらを再スローして、コールスタックがそれらのパブリックメソッドで始まるようにすることができます。
ここでの答えはどれも違いを示していません。これは違いを理解するのに苦労している人々に役立つ可能性があります。次のサンプルコードを検討してください。
using System;
using System.Collections.Generic;
namespace ExceptionDemo
{
class Program
{
static void Main(string[] args)
{
void fail()
{
(null as string).Trim();
}
void bareThrow()
{
try
{
fail();
}
catch (Exception e)
{
throw;
}
}
void rethrow()
{
try
{
fail();
}
catch (Exception e)
{
throw e;
}
}
void innerThrow()
{
try
{
fail();
}
catch (Exception e)
{
throw new Exception("outer", e);
}
}
var cases = new Dictionary<string, Action>()
{
{ "Bare Throw:", bareThrow },
{ "Rethrow", rethrow },
{ "Inner Throw", innerThrow }
};
foreach (var c in cases)
{
Console.WriteLine(c.Key);
Console.WriteLine(new string('-', 40));
try
{
c.Value();
} catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
}
次の出力が生成されます。
Bare Throw:
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
at ExceptionDemo.Program.<>c.<Main>g__bareThrow|0_1() in C:\...\ExceptionDemo\Program.cs:line 19
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Rethrow
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<>c.<Main>g__rethrow|0_2() in C:\...\ExceptionDemo\Program.cs:line 35
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
Inner Throw
----------------------------------------
System.Exception: outer ---> System.NullReferenceException: Object reference not set to an instance of an object.
at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 43
--- End of inner exception stack trace ---
at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 47
at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64
前の回答で示したように、基本スローは、失敗した元のコード行(12行目)と、例外が発生したときに呼び出しスタックでアクティブな他の2つのポイント(19行目と64行目)の両方を明確に示しています。
再スローのケースの出力は、それが問題である理由を示しています。このように例外が再スローされると、例外には元のスタック情報が含まれません。throw e(行35)と最も外側の呼び出しスタックポイント(行64)のみが含まれていることに注意してください。この方法で例外をスローすると、問題の原因としてfail()メソッドを追跡することが難しくなります。
最後のケース(innerThrow)は最も複雑で、上記のどちらよりも多くの情報が含まれています。新しい例外をインスタンス化しているので、コンテキスト情報(ここでは「外部」メッセージですが、新しい例外の.Data辞書に追加することもできます)を追加する機会があり、すべての情報を元の状態で保持します例外(ヘルプリンク、データディクショナリなどを含む)。