3

System.IO には関数があります: string File.ReadAllText( string path );

File.ReadAllText を呼び出し、考えられるすべての例外を処理し、true/false を返し、エラー メッセージを保存する関数を作成しようとしています。

私が持っているのはこれです:

public static class FileNoBS
{
    public static bool ReadAllText( string path, out string text, out string errorMessage )
    {
        errorMessage = null;
        text = null;
        bool operationSuccessful = false;

        try
        {
            text = System.IO.File.ReadAllText( path );
            operationSuccessful = true;
        }
        catch ( ArgumentNullException e )
        {
            errorMessage = "Internal software error - argument null exception in FileNoBs.ReadAllText\nMessage: " + e.Message;
        }
        catch ( ArgumentException e )
        {
            errorMessage = "Internal software error - path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars in FileNoBs.ReadAllText.\nMessage: " + e.Message;
        }
        catch ( PathTooLongException e )
        {
            errorMessage = "The specified path was too long.\nMessage: " + e.Message;
        }
        catch ( DirectoryNotFoundException e )
        {
            errorMessage = "The specified directory was not found.\nMessage: " + e.Message;
        }
        catch ( FileNotFoundException e )
        {
            errorMessage = "The file specified in path was not found.\nMessage: " + e.Message;
        }
        catch ( IOException e )
        {
            errorMessage = "An I/O error occurred while opening the file.\nMessage: " + e.Message;
        }
        catch ( UnauthorizedAccessException e )
        {
            errorMessage = @"UnauthorizedAccessException

path specified a file that is read-only.
-or-
This operation is not supported on the current platform.
-or-
path specified a directory.
-or-
The caller does not have the required permission.\nMessage: " + e.Message;
        }
        catch ( NotSupportedException e )
        {
            errorMessage = "path is in an invalid format.\nMessage: " + e.Message;
        }
        catch ( SecurityException e )
        {
            errorMessage = "You do not have the required permission.\nMessage: " + e.Message;
        }

        return operationSuccessful;
    }
}

値を返す関数で制御フローがどのように機能するかわかりません。UnauthorizedAccessException がキャッチされ、errorMessage が設定されているとしましょう

    errorMessage = "You do not have the required permission..."

最終的に毎回実行されることは知っていますが、コンパイラーは最終ブロック内に戻ることを許可しません。それで、私のリターンは到達するかどうか?

別の質問は、公式のガイドラインに従いながら、これを単純化する方法です。「一般に、回復方法がわかっている例外のみをキャッチする必要があります。

File クラス (Move、Copy、Delete、ReadAllText、WriteAllText) から必要なすべての関数を実行し、次に Directory クラスを実行して、気にしないすべての例外をキャッチし、キャッチしないすべての例外をキャッチするためだけに、これらすべての長いコード ブロックを実行することを恐れています。それらの数が多すぎると、マイクロソフトはそれが悪いと言います。

ありがとうございました。

編集:これは例外を処理していない、これは「何か他のもの」であるなどのコメントを受け取りました。

私は自分のコードのクライアントであり、次のようなことをしたいと思っています:

if ( !FileNoBS.ReadAllText( path, text, errorMessage ) ) {
   MessageBox.Show( errorMessage );
   return;
}
// continue working with all errors taken care of - don't care for whatever reason file wasn't opened and read, user is notified and I am moving on with my life
4

6 に答える 6

4

try ブロックまたは catch ブロックに戻りがないため、戻りに到達します。

一般に、発生する可能性があると予想される例外のみをキャッチし、それらを処理する方法が必要です。たとえば、指定されたパスから見つからないファイルを処理し、代わりにデフォルトのファイルを返したい場合があります。他の例外がキャッチされないようにする必要があります。これにより、予期しないことが発生したことがわかり、すべての例外をキャッチして隠蔽することはありません。

于 2013-05-27T05:44:11.407 に答える
2

コメントで述べたように、各メッセージを手動で設定するよりも、より高いレベルで例外を処理し、単に例外メッセージを表示する方がよいでしょう。この場合、例外からのメッセージは十分に説明的だと思います。

    public static class FileNoBS
    {
        public static string ReadAllText(string path)
        {
            return System.IO.File.ReadAllText( path );
        }   
    }

次に、アプリケーションのより高いレベルでこのように使用します。私は通常、すべてのアプリケーション例外を処理してログに記録し、必要に応じてメッセージ ボックスを表示するための一般的なハンドラーを用意しています。

    try
    {
        var text = FileNoBS.ReadAllText("file.ext");
    }
    catch(Exception e)
    {
    Console.WriteLine(e.Message);
    }
于 2013-05-27T06:02:40.513 に答える
1

例外をキャッチする代わりに、それらの例外が最初にスローされる状況を回避するように努める必要があります。あなたの場合、呼び出す前にいくつかの入力検証が必要ですReadAllText

  • null のパスを受け入れないでください - これが例外につながることがわかっているので、そうなる前に処理してください
  • 存在しないファイルへのパスを決して受け入れない -File.Exists(path)呼び出しの前に使用する
  • 空の文字列や無効な文字を含むパスなど、不正な形式のパスを受け入れない - これは例外につながります

これらのテストは、入力が発生した場所で実行する必要があります。つまり、ユーザーがそれらを入力した場合は、それらを使用する前に検証してください。それらがDBまたは他の場所からのものである場合は、使用する前にそこで検証してください。ユーザー入力でない場合、それらはすべてシステム エラーの兆候であり、ユーザーが心配する必要があるものとしてではなく、そのように扱う必要があります。

セキュリティ例外は、前もってテストするのがやや難しくなる可能性があり、多くの場合、違反が発生することは例外的であるため、例外が発生してもまったく問題ありません。もちろん、プログラムをクラッシュさせるべきではありませんが、ユーザーへのエラーメッセージで処理する必要があります (ユーザー入力に基づいている場合、これにつながるシステム生成データである場合は、コードレベルで修正する必要があるシステムエラーの識別です) )。多くの場合、一部のライブラリ メソッドよりも、呼び出しが発生する場所でこれを行う方が適切です。

IOExceptions2つのバケツに入れることができるからです。1 回回復可能 (通常は再試行) で、1 回回復不能。少なくとも、例外についてユーザーにフィードバックを提供してください。そうすれば、ユーザーは再試行できるようになります。

エラー修正ロジックの一部にする必要がある非常に一般的なルールは、無効なデータがシステム内に浮遊しないようにすることです。すべてのオブジェクトが不変条件を管理していることを確認してください (コード コントラクトなどのツールが利用可能です)。ユーザー (または他のシステム) からの無効な入力を、例外が発生したときではなく受信したときに拒否します。

すべての入力検証を行っても Eg がArgumentNullExceptionある場合、それはプログラムのロジックにエラーがあることを示しています。バグをリリースする前に、テストで簡単に見つけて修正できるようにしたいものです。このエラーを隠そうとしないでください。

于 2013-05-27T06:45:42.493 に答える
0

return ステートメントは、プログラムが終了する前にプログラムの最後に配置される前に、コードで例外が発生した場合に呼び出されます。

「Exception」タイプ自体のような高レベルの例外タイプを持つ単一の例外ハンドラーを配置し、例外メッセージを出力またはログに記録することをお勧めします。各メソッドで非常に多くの例外ハンドラーを指定すると、実際にはメソッド自体に投入する必要がある多くのエネルギーが必要になります。

        try
        {
            return ReadAllText("path", "text", "error");
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
        return false;

したがって、メソッドが呼び出されるとすぐに戻ります。それ以外の場合は、例外が出力/ログに記録され、メソッドは false を返します。

ただし、場合によっては、いくつかの明示的な例外ハンドラーについて言及することもできます。

于 2013-05-27T06:58:20.073 に答える
0

他のエラーが発生しなければ、はい。

最後に追加します:

catch (Exception e)
{
    errormessage = "An unexpected error has occured.";
}

return operationSuccessful;

ただし、エラーが発生した場合でも、これは常に成功を返します。それがあなたが望むものなのか、それとも変数の名前が悪いのかわかりません。

于 2013-05-27T05:48:48.117 に答える
-2

はい 値を返します。

ただし、returnfinally ステートメントで値を処理することをお勧めします。

いずれにせよ operationSuccessful 値を返したい場合は、次のように catch ブロックの後に finally ブロックを記述します。

finally
{
  return operationSuccessful;
}
于 2013-05-27T05:45:19.283 に答える