.NET:必要な構成設定がない場合にスローする例外はどれですか?


123

標準的なシナリオは次のとおりです。

if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
   throw new SomeStandardException("Application not configured correctly, bozo.");

問題は、例外がどれであるSomeStandardExceptionかが完全にわからないことです。

私は3.5フレームワークを熟読して2有望な候補が見つかりました:ConfigurationExceptionConfigurationErrorsException

System.Configuration.ConfigurationException

構成システムエラーが発生したときにスローされる例外。

備考

ConfigurationExceptionアプリケーションの試みは、読み取りまたは構成ファイルへの書き込みデータが、失敗したした場合、例外がスローされます。これには、構成ファイル内の不正なXML、ファイルのアクセス許可の問題、および無効な値を持つ構成プロパティが含まれる可能性があります。

注意:

ConfigurationExceptionオブジェクトは、下位互換性のために維持されます。ConfigurationErrorsException オブジェクトは、構成システムのオブジェクトを置き換えます。

この例外は実際には私が必要としているものに完璧に聞こえますが、廃止されたとマークされているので、ixnayはついに発表しました。

これは私たちを徹底的に不可解に導きますConfigurationErrorsException

System.Configuration.ConfigurationErrorsException

現在の値は、EnableSessionState値の1つではありません。

ご覧のとおり、そのドキュメントはまったく役に立ちません。(ローカルヘルプとオンラインヘルプの両方でそのようになっています。)クラス自体を調べてみると、私が望むものに対して大幅な過剰であることがわかります。

簡単に言うと、アプリケーションの構成設定がないか、無効な値が含まれている場合にスローされる標準の例外が必要です。フレームワークには、アプリケーションで使用できるようにそのような例外が組み込まれていると思います。(確かにそうでしたが、時代遅れとマークされ、スコープがはるかに大きいものに置き換えられました。)

もしあれば、あなたはこれにどのような解決策を使用していますか?私はそれを吸い上げてこれについて自分の例外をロールバックする必要がありますか?

補遺を編集

デフォルト値を指定して続行できるかどうかを尋ねる人もいます。特定のケースでは、はい、そのようなケースでは、例外はスローされません。ただし、特定の設定では、これは適用されません。たとえば、データベースサーバー名と認証情報、認証サーバー、インストールされているサードパーティアプリケーションへのパスなどです。

また、私が主に取り組んでいるアプリケーションはバッチモードで実行されているコンソールアプリケーションであり、mainメソッドによってキャッチされ、適切に構成されていない場合は適切にログに記録される例外をスローすることにも注意してください。(これは私が継承したレガシーコードであり、現在すべてが桃色だと想定しています。)


1
のドキュメントSystem.Configuration.ConfigurationErrorsException が更新されました。
slolife

回答:


36

フレームワークの既存の例外に例外を投げることに制限されません。既存の例外を使用することを決定した場合、その文書の説明に必ず従う必要はありません。ドキュメントは、フレームワークが特定の例外を使用する方法説明しますが、既存の例外の使用/再利用選択する方法に制限を意味するものではありません。

それはあなたのアプリケーションです-それを文書化し、構成値が欠落している特定の場合にスローされる例外を明確に示している限り、好きな例外を使用できます。欠損値の非常に具体的な表示が必要な場合は、独自のConfigurationSettingMissing例外を記述することを検討してください。

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

編集:この場合に独自の例外を作成すると、例外がフレームワークまたはアプリケーションのどこから発生しているのかについて混乱が生じないことを保証するという追加の利点があります。フレームワークがカスタム例外をスローすることはありません。

更新:コメントに同意するため、サブクラスをExceptionからConfigurationErrorsExceptionに変更しました。アプリケーション固有の例外が必要でない限り、例外クラスを回避して、可能な限り既存のフレームワーク例外からカスタム例外をサブクラス化することは、一般的に良い考えだと思います。


17
ややそう思わない。既存の例外を使用する場合は、ドキュメントで使用されているように正確に使用する必要があります。そうしないと、後から来るユーザーを混乱させてしまいます。別のことをするつもりなら、あなたが言ったように、あなた自身の例外を作成してください。
ロバートC.バース

1
同意しません。カスタム例外をキャッチするシナリオがない限り、構成エラーの場合とは異なり、既存のタイプ(ConfigurationErrorsException)を再利用することをお勧めします。また、カスタムタイプを作成する場合は、ConfigurationErrorsExceptionなどの関連タイプから派生させます。
Joe

@Robert&Joe-特定のケース(欠損値)が一般的なケース(ConfigurationErrorsException)に適合する限り、ある程度の柔軟性があるというだけで、既存のフレームワークの例外を目的の機能と矛盾して使用することはお勧めしません。
Dave Swersky、

1
ConfigurationErrorsExceptionとその派生クラスが保護されたOnErrorメソッドまたはグローバルASAXエラーイベントによってキャッチされないため、ASP.NETアプリケーション内で例外をスローする場合、これに問題が発生する可能性があります。....私が投稿したこの質問を参照してください stackoverflow.com/questions/25299325/...
ミック・

48

個人的には、構成システムではなくオブジェクトの状態に問題があるため、InvalidOperationExceptionを使用します。結局のところ、これらの設定を構成するのではなく、コードで設定できるようにしないでください。ここで重要なのは、app.configに行がなかったことではなく、必要な情報が存在しなかったことです。

私にとって、ConfigurationException(およびその代替、ConfigurationErrorsException-誤解を招くMSDNドキュメントにもかかわらず)は、構成の保存、読み取りなどのエラーのためのものです。


ASP.NETページで保護されたOnErrorメソッドによって処理されるため、InvalidOperationExceptionを選択しましたが、ConfigurationErrorsExceptionおよびそれから派生したすべての例外はそうではありません
Mick

2
構成が間違っている場合にInvalidOperationExceptionが発生すると、これは本当に驚きます。
keuleJ

18

ダニエル・リチャードソンが言ったように、ConfigurationErrorsExceptionが使用すべきものです。一般に、独自のカスタム例外タイプを作成することは、それらを処理するシナリオがある場合にのみお勧めします。通常致命的である構成エラーの場合、これはまれなケースであるため、通常は既存のConfigurationErrorsExceptionタイプを再利用する方が適切です。

.NET 2.0より前は、System.Configuration.ConfigurationExceptionを使用することが推奨されていました。.NET 2.0では、ConfigurationExceptionは廃止されました。理由は私には明確ではありませんでした。また、ConfigurationErrorsExceptionを使用するように推奨が変更されました。

ヘルパーメソッドを使用して例外をスローするので、.NET 1.xから2.0に移行するとき、またはMicrosoftが推奨事項を再度変更する場合、スローされる例外を1か所で簡単に変更できます。

if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
   throw CreateMissingSettingException("foobar");
}

...

private static Exception CreateMissingSettingException(string name)
{
    return new ConfigurationErrorsException(
        String.Format
        (
        CultureInfo.CurrentCulture,
        Properties.Resources.MissingConfigSetting,
        name
        )
        );
}


7

ConfigurationErrorsExceptionあなたが説明する状況でスローする正しい例外です。以前のバージョンのMSDNドキュメントはConfigurationErrorsException、より理にかなっています。

http://msdn.microsoft.com/en-us/library/system.configuration.configurationerrorsexception(VS.80).aspx

以前のMSDNの概要と解説は次のとおりです。

  • 構成システムエラーが発生したときにスローされる例外。
  • ConfigurationErrorsException 構成情報の読み取りまたは書き込み中にエラーが発生した場合に例外がスローされます。

7
ドキュメントから:「このAPIは製品インフラストラクチャをサポートし、コードから直接使用するためのものではありません。ConfigurationErrorsExceptionクラスの新しいインスタンスを初期化します。」
Oleg Sh

6

ConfigurationElementクラス(ConfigurationSectionなどの多くの構成関連クラスの基本クラス)には、OnRequiredPropertyNotFoundというメソッドがあります(他のヘルパーメソッドもあります)。あなたはおそらくそれらを呼び出すことができます。

OnRequiredPropertyNotFoundは次のように実装されています。

protected virtual object OnRequiredPropertyNotFound(string name) {
    throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }

1

私はそれを吸い上げて自分でロールバックします...しかし、それを行う前に、システムにこの構成設定のデフォルト値を想定させることは可能ですか?私は通常、運用管理者が見落とす可能性があるすべての設定についてこれを実行しようとします...(または、できるだけ多くの設定について、おそらく言う必要があります-システムによってはデフォルトの決定を行わせるのが明らかに適切でない場合があります。 ..)

一般に、カスタム例外はそれほどの労力ではありません...ここに例があります...

[Serializable]
public class MyCustomApplicationException : ApplicationException
{
    #region privates
    #endregion privates

    #region properties
    #endregion properties

    public MyCustomApplicationException (string sMessage,
        Exception innerException)
        : base(sMessage, innerException) { }
    public MyCustomApplicationException (string sMessage)
        : base(sMessage) { }
    public MyCustomApplicationException () { }

    #region Serializeable Code
    public MyCustomApplicationException (
       SerializationInfo info, StreamingContext context)
        : base(info, context) { }
    #endregion Serializeable Code
}

2
MSDN:...独自の例外を作成する必要があるアプリケーション、[...] Exceptionクラスからカスタム例外を派生させます。当初、カスタム例外はApplicationExceptionクラスから派生する必要があると考えられていました。しかし、実際には、これは重要な価値を追加することがわかっていません。
Gaspar Nagy、

はい、私は...フレームワークをコード化されたMSのプログラマは、このような区別の重要性を破壊するApplicationExceptionをからの多数のCLR例外を、派生ので、私はそれに害を見ないようには..私はまだ、かかわらず、それを行うたと思う
チャールズBretana

1

構成ファイルに使用できる代替方法は、ではなくカスタム構成セクションを使用することAppSettingsです。このようにして、プロパティIsRequiredと構成システムがこのチェックを処理するように指定できます。プロパティが欠落している場合はそれがスローされるConfigurationErrorsExceptionので、あなたはあなたのケースでその例外を使用するべきであるという答えをサポートしていると思います。


0

私の一般的なルールは:

  1. 不足している構成のケースがあまり一般的ではなく、他の例外とは別にこのケースを処理したくないと思う場合は、適切なメッセージを含む基本的な「Exception」クラスを使用します。

    新しい例外をスローする(「ここに私のメッセージ」)

  2. 他のほとんどの例外とは異なる方法でこのケースを処理したい可能性が高い、または可能性が高いと思われる場合は、すでにここで提案されているように、自分のタイプをロールバックします。


0

私はあなたの質問の前提に反対する傾向があります:

簡単に言えば、アプリケーションの構成設定がないか、無効な値が含まれている場合にスローされる標準の例外が必要です。フレームワークには、アプリケーションで使用できるようにそのような例外が組み込まれていると思います。(確かにそうでしたが、廃止されたとマークされ、スコープがはるかに大きいものに置き換えられました。)

System.Exception(Exception Class)に関するMSDNドキュメントによれば、パフォーマンス上の理由から(スタックオーバーフローなどで他の人が指摘しているように)、ユーザー入力エラーに対して例外をスローするべきではありません。これは、よく-ユーザー入力が誤って入力された場合に関数がfalseを返さず、アプリケーションを正常に終了できないのはなぜですか?これは、設計上の問題よりも、どの例外をスローするかという問題のようです。

あなたが本当にあれば他の人が、指摘したように持って何らかの理由- -スローされた例外にあなたはのSystem.Exceptionから継承して、あなたの例外の種類を定義することができなかった理由を何らかの理由ではありません。


2
この特定のシナリオでパフォーマンスが重要になるのはなぜですか?IUCの場合、例外は1回だけスローされ、プロセスはおそらく(とにかく、ユーザーに素敵なポップアップを表示した後)とにかく停止します。(続く...)

2
例外をスローする代わりにエラーコードを返すと、エラー情報を自分で呼び出しスタックに伝達する必要があるため、面倒な場合があります。複数のスタックフレームに伝播する可能性のある比較的まれなエラーには、例外を使用する必要があります。ここでは両方が適用されます。

1
「アプリケーションの構成設定が見つからないか、無効な値が含まれている場合」は、ユーザー入力の誤りとは異なります。これは欠落している基本構成です。カスタム例外であり、アプリの実行を停止する必要があります。
jcollum 2009年

2
この特定のアプリケーションでは、構成ファイルの設定によってほぼ完全に駆動されます。設定が含まれていない場合(暗号化されている場合)、アプリケーションは続行できず、終了する必要があります。例外は事実上必要です。
Mike Hofer、

1
これは確かにセマンティクスに入る可能性があり、コードの構造は明らかに状況に最適な実装を決定します。それでも、設計に自由な統治があったとしても、エラーをログに記録するためのオブジェクトと例外に対する優雅な出口を使用します。パフォーマンスが問題かどうかは関係ありません。
マットジョーダン

-2

XML例外を継承するか、それをそのまま使用することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.