記事C#-シリアル化可能なDTOのデータ転送オブジェクトを見ています。
この記事には、次のコードが含まれています。
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
throw ex;
}
}
記事の残りの部分は(初心者には)正気で合理的に見えますが、そのtry-catch-throwはWtfExceptionをスローします...これは例外をまったく処理しないこととまったく同じではありませんか?
エルゴ:
public static string SerializeDTO(DTO dto) {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
または、C#でのエラー処理に関する基本的な何かが欠けていますか?Java(チェックされた例外を除く)とほとんど同じですよね?...つまり、どちらもC ++を改良しました。
スタックオーバーフローの質問パラメータなしのキャッチを再スローすることと何もしないことの違いは?try-catch-throwは-no-opであるという私の主張を支持しているようです。
編集:
将来このスレッドを見つけた人のために要約すると...
しない
try {
// Do stuff that might throw an exception
}
catch (Exception e) {
throw e; // This destroys the strack trace information!
}
スタックトレース情報は、問題の根本原因を特定するために重要な場合があります。
行う
try {
// Do stuff that might throw an exception
}
catch (SqlException e) {
// Log it
if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
// Do special cleanup, like maybe closing the "dirty" database connection.
throw; // This preserves the stack trace
}
}
catch (IOException e) {
// Log it
throw;
}
catch (Exception e) {
// Log it
throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
// Normal clean goes here (like closing open files).
}
(Javaのように)具体性の低い例外の前に、より具体的な例外をキャッチします。
参照:
最初; 記事のコードがそれを行う方法は悪です。throw ex
例外の呼び出しスタックを、このthrowステートメントがあるポイントにリセットします。例外が実際に作成された場所に関する情報が失われます。
次に、そのようにキャッチして再スローした場合、付加価値は見られません。上記のコード例throw ex
は、try-catchがなくても同じくらい良い(または、少し言えばさらに良い)でしょう。
ただし、例外をキャッチして再スローしたい場合があります。ロギングはそれらの1つである可能性があります。
try
{
// code that may throw exceptions
}
catch(Exception ex)
{
// add error logging here
throw;
}
これをしないでください、
try
{
...
}
catch(Exception ex)
{
throw ex;
}
スタックトレース情報が失われます...
どちらか、
try { ... }
catch { throw; }
または
try { ... }
catch (Exception ex)
{
throw new Exception("My Custom Error Message", ex);
}
再スローする理由の1つは、たとえば、さまざまな例外を処理している場合です。
try
{
...
}
catch(SQLException sex)
{
//Do Custom Logging
//Don't throw exception - swallow it here
}
catch(OtherException oex)
{
//Do something else
throw new WrappedException("Other Exception occured");
}
catch
{
System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
throw; //Chuck everything else back up the stack
}
C#(C#6より前)はVBがサポートするCILの「フィルターされた例外」をサポートしていないため、C#1-5で例外を再スローする理由の1つは、catch()の時点で十分な情報がないことです。実際に例外をキャッチするかどうかを決定します。
たとえば、VBでは次のことができます
Try
..
Catch Ex As MyException When Ex.ErrorCode = 123
..
End Try
...これは、異なるErrorCode値を持つMyExceptionsを処理しません。v6より前のC#では、ErrorCodeが123でない場合、MyExceptionをキャッチして再スローする必要がありました。
try
{
...
}
catch(MyException ex)
{
if (ex.ErrorCode != 123) throw;
...
}
C#6.0以降、VBと同じようにフィルタリングできます。
try
{
// Do stuff
}
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
// Handle, other exceptions will be left alone and bubble up
}
次のようなコードを持つ私の主な理由:
try
{
//Some code
}
catch (Exception e)
{
throw;
}
これは、インスタンス化された例外オブジェクトを持つキャッチにブレークポイントを設定できるようにするためです。私は開発/デバッグ中にこれをたくさん行います。もちろん、コンパイラは未使用のすべてのeについて警告を表示します。理想的には、リリースビルドの前にそれらを削除する必要があります。
ただし、デバッグ中は便利です。
例外を再スローする正当な理由は、例外に情報を追加したい場合、または元の例外を独自の作成の1つでラップしたい場合です。
public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
}
catch(Exception ex) {
string message =
String.Format("Something went wrong serializing DTO {0}", DTO);
throw new MyLibraryException(message, ex);
}
}
これは、例外をまったく処理しないこととまったく同じではありませんか?
正確には、それは同じではありません。例外のスタックトレースをリセットします。これはおそらく間違いであり、したがって悪いコードの例であることに同意します。
exをスローしたくない-これはコールスタックを失うからです。例外処理(MSDN)を参照してください。
そして、はい、try ... catchは何の役にも立ちません(何らかの理由でこの情報を公開したくない場合を除いて、コールスタックが失われることを除けば-実際にはもっと悪いです-)。
人々が言及していない点は、.NET言語は実際には適切な区別をしていませんが、例外が発生したときにアクションを実行する必要があるかどうか、およびそれを解決するかどうかの問題は、実際には別個の質問であるということです。解決する見込みのない例外に基づいてアクションを実行する必要がある場合が多く、例外を「解決」するために必要なのは、スタックを特定のポイントに巻き戻すことだけである場合もあります。それ以上のアクションは必要ありません。 。
「処理」できるものだけを「キャッチ」する必要があるという一般的な知恵のため、例外が発生したときにアクションを実行する必要がある多くのコードはそうではありません。たとえば、多くのコードはロックを取得し、保護されたオブジェクトを「一時的に」その不変条件に違反する状態にし、次にオブジェクトを正当な状態にし、他の誰かがオブジェクトを見る前にロックを解除します。オブジェクトが危険なほど無効な状態にあるときに例外が発生した場合、一般的な方法は、オブジェクトをその状態のままにしてロックを解除することです。より良いパターンは、オブジェクトが「危険な」状態にあるときに発生する例外を明示的に無効にすることです。これにより、今後ロックを取得しようとするとすぐに失敗します。このようなパターンを一貫して使用すると、いわゆる「ポケモン」例外処理の安全性が大幅に向上します。IMHOは、主に、最初に適切なアクションを実行せずに例外を浸透させるコードが原因で評判が悪くなります。
ほとんどの.NET言語では、コードが例外に基づいてアクションを実行する唯一の方法は、コードに対してcatch
(例外を解決しないことがわかっている場合でも)、問題のアクションを実行してから再実行することthrow
です)。コードがどの例外がスローされるかを気にしない場合の別の可能なアプローチはok
、try/finally
ブロックでフラグを使用することです。セットok
にフラグをfalse
ブロックする前に、とにtrue
ブロックが終了する前に、および任意の前にreturn
ブロック内だという。次に、内でfinally
、ok
が設定されていない場合、例外が発生したに違いないと想定します。このようなアプローチは、意味的にはcatch
/よりも優れていますが、throw
醜く、本来よりも保守が困難です。
これは、プログラミングがライブラリまたはdll用に機能する場合に役立ちます。
この再スロー構造を使用して、呼び出しスタックを意図的にリセットし、関数内の個々の関数からスローされた例外を確認する代わりに、関数自体から例外を取得することができます。
これは、スローされた例外がよりクリーンになり、ライブラリの「ルート」に入らないようにするために使用されていると思います。
他の多くの回答は、例外を再スローする理由の良い例を提供しますが、「最終的に」シナリオについて言及した人はいないようです。
この例は、カーソルを(たとえば、待機カーソルに)設定するメソッドがあり、メソッドにいくつかの出口点があり(たとえば、()return;)、カーソルがでリセットされるようにしたい場合です。メソッドの終わり。
これを行うには、すべてのコードをtry / catch / finallyでラップします。最後に、カーソルを右カーソルに戻します。有効な例外を埋めないように、キャッチに再スローします。
try
{
Cursor.Current = Cursors.WaitCursor;
// Test something
if (testResult) return;
// Do something else
}
catch
{
throw;
}
finally
{
Cursor.Current = Cursors.Default;
}
キャッチスローの考えられる理由の1つは、スタックのより深いところにある例外フィルターがフィルターダウンされないようにすることです(ランダムな古いリンク)。しかしもちろん、それが意図されていれば、そこにそう言っているコメントがあるでしょう。
それはあなたがcatchブロックで何をしているか、そしてあなたがエラーを呼び出し元のコードに伝えたいかどうかに依存します。
Catch io.FileNotFoundExeption ex
別のファイルパスなどを言ってから使用しても、エラーが発生します。
また、Throw
代わりにThrow Ex
実行すると、完全なスタックトレースを保持できます。Throw exは、throwステートメントからスタックトレースを再開します(それが理にかなっていることを願っています)。
あなたが投稿したコードの例では、実際には、例外をキャッチする意味はありません。キャッチには何も行われていないため、再スローされるだけです。実際、コールスタックが失われるため、害はありません。 。
ただし、例外が発生した場合は、例外をキャッチしてロジックを実行し(たとえば、ファイルロックのSQL接続を閉じる、またはログを記録する)、呼び出し元のコードにスローして処理します。これは、ビジネスレイヤーを実装するコーダーに例外を処理させたい場合があるため、フロントエンドコードよりもビジネスレイヤーで一般的です。
繰り返しになりますが、投稿した例で例外をキャッチする意味はありません。そのようにしないでください!
申し訳ありませんが、「改良されたデザイン」などの多くの例は、依然としてひどいにおいがするか、非常に誤解を招く可能性があります。{} catch {log; throw}はまったく無意味です。例外ログは、アプリケーション内の中央の場所で実行する必要があります。とにかく例外がスタックトレースをバブルアップします。システムの境界の近くのどこかに例外を記録してみませんか?
コンテキスト(つまり、1つの例ではDTO)をログメッセージにシリアル化する場合は注意が必要です。ログファイルにアクセスできるすべての人の手に渡りたくない機密情報を簡単に含めることができます。また、例外に新しい情報を追加しない場合、例外の折り返しのポイントは実際にはわかりません。古き良きJavaにはそのためのいくつかのポイントがあります。呼び出し元は、コードを呼び出すときに予想される例外の種類を知っている必要があります。.NETにはこれがないため、私が見たケースの少なくとも80%では、ラッピングは何の役にも立ちません。
他の人が言ったことに加えて、キャッチと再スローはノーオペレーションではないことを示す関連する質問への私の答えを参照してください(VBにありますが、コードの一部はVBからC#で呼び出される可能性があります)。
シナリオcatch-log-rethrowについて話している回答のほとんど。
代わりにあなたのコードでそれを書き込むので、特に、AOPを使用することを検討しPostsharp.Diagnostic.Toolkit OnExceptionOptions IncludeParameterValueとIncludeThisArgumentで
を介して例外を再スローthrow
することは、現在の例外を処理する特定のコードがない場合、または特定のエラーケースを処理するロジックがあるが、他のすべてをスキップしたい場合に役立ちます。
例:
string numberText = "";
try
{
Console.Write("Enter an integer: ");
numberText = Console.ReadLine();
var result = int.Parse(numberText);
Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
if (numberText.ToLowerInvariant() == "nothing")
{
Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}
else
{
throw;
}
}
finally
{
Console.WriteLine("Freed some resources.");
}
Console.ReadKey();
ただし、catchブロックで条件節を使用して、これを行う別の方法もあります。
string numberText = "";
try
{
Console.Write("Enter an integer: ");
numberText = Console.ReadLine();
var result = int.Parse(numberText);
Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}
finally
{
Console.WriteLine("Freed some resources.");
}
Console.ReadKey();
このメカニズムは、.NETランタイムが例外オブジェクトを再スローする前に再構築する必要がないため、例外を再スローするよりも効率的です。
特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。
ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。
ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。
サンディエゴコミックコンは今週開幕し、オタクのアナウンス、ポスター、予告編、お気に入りの番組や映画のからかいでいっぱいになります。SDCCは、コンベンションフロア全体の多くのパネルで行われているため、すべてに対応するのは難しい場合があります。
小さなアプリ開発者は金曜日に発表された法的な和解でグーグルから9千万ドルをこじ開けた。アップルとの同様の合意に続いて熱くなった。金曜日のブログ投稿で、Googleは、Androidメーカーが市場での優位性を悪用してPlayストア経由でのアプリ内購入に対して30%の料金を不当に請求したと主張するアプリ開発者との訴訟を解決するために、9千万ドルを支払うことに合意したと述べました。
今週、RadioShackのTwitterアカウントは、奇妙なものから完全にひどいものになりました。短い順序で、会社のフィード全体が、バイブレーター、「ビッグティット」(スペルミス)、有名人やその他の企業アカウントを荒らしているツイートなど、NSFW素材の真の山になりました。
大型ハドロン衝突型加速器のトンネル内にあるコンパクトミュオンソレノイド(CMS)検出器。2012年7月4日、CERNの科学者たちは、1960年代に最初に提案された素粒子であるヒッグス粒子の観測を確認しました。
Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday
シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。
オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。
Bien. Hay un momento en toda salida al espacio exterior en el que de la tensión, la velocidad y las altas temperaturas derivadas del cruce de estratosfera a ionosfera se pasa a un momento de súbita calma, donde se despliega la vista completa del paisaje espacial que nos rodea.
1.ドラマを見た後、起業する考えはありますか?あなたのビジネスはボトルネックに遭遇しましたか?方向性がなくてわからない場合は、ドラマを追いかけて行くことを心からお勧めします。(?)ブラフではなく、最も完璧なビジネス例を隠すドラマがあります。2.ブレイキング・バッドとその弁護士ドラマ「ブレイキング・バッド」を見た友人たちは、演劇の中で、穏やかな表情で、弁護士のソウル・グッドマンに深く感銘を受けなければなりません。口を開けて、感覚の弱い傭兵の性格を持っています。道徳の面で、サル・グッドマンは無意識のうちに劇に欠かせない役割を果たし、彼自身のシリーズ「絶望的な弁護士」(ベター・コール・ソール)を生み出しました。ウェントウのテキストとビデオは、劇中のソウル・グッドマンのテレビコマーシャルです。製品(サービス)、競争戦略、市場ポジショニング、ブランド名、ターゲット顧客グループ、コミュニケーション軸から広告まで、サル・グッドマンの役割のビジネス設定は、「最低」と見なすことができる超超超超超超完全です。ブランドコミュニケーションのコスト」「変化」のモデル。なぜ?私の分析をご覧ください。3.ソウル・グッドマンの「事業戦略」1.基本情報ブランド名:Saul Goodman製品:法律相談サービス対象顧客:麻薬中毒、飲酒運転、事故など。法律知識の欠如は、一般的に公立弁護士にしか余裕がなく、真面目な弁護士も「特別な法律を持つ消費者」を避けます。恐れてはいけない「ニーズ」。コミュニケーションの主軸:この国のすべての男性、女性、子供は有罪判決を受けるまで無実だと思います。地域:アルバカーキ市スローガン:Thrallに電話したほうがいいです!(ベター・コール・ソール)広告:2つの可能性のある犯罪状況をシミュレートします+サウルの主張+サウルのスローガン2をより適切に呼び出します。