1

例外処理のグッド プラクティスに関する記事をいくつか読みました。そのほとんどは、作成者が予想していた予期しない例外に取り組みました。私が行っている可能性のある悪い慣行を明確にして排除したいだけです。これらの問題はすでに発生していると予想しているため、例外をスローするのは少し冗長だと思います。

私がこのコードを持っているとしましょう:

string fileName = Path.Combine(Application.StartupPath, "sometextfile.txt");

// There's a possibility that the file doesn't exist <<<<<<<<<<<<<<<<<<<<<
if (!File.Exists(fileName))
{
   // Do something here
   return;
}

// Therefore, this will return an exception
using (StreamReader file =
     new StreamReader(fileName))
{
     // Some code here
}

当然、「ファイルが見つかりません」というメッセージ ボックスをユーザーに通知します。これを行う効率的またはより良い方法はありますか?

私が持っている別のアイデアは、予想されるエラーコードを含む列挙型を作成し、その特定の状況のエラーメッセージを表示する MessageBox を呼び出すメソッドを作成することです:

enum ErrorCodes {null, zero, ...}
public void showError(ErrorCodes error)
{
    string message;
    switch (error)
        {
        case ErrorCode.null:
        {
             message = "value cannot be null";
             break;
        }
        case ErrorCode.zero:
        {
             message = "cannot divide by zero";
             break;
        }
}

MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
4

2 に答える 2

1

ファイルにアクセスしようとしているコードがフロント エンド (たとえば、クリック時のイベント ハンドラー) にある場合は、エラー状況を確認し、メッセージを表示して戻ることができます。

私があなたの質問を正しく理解していれば、あなたはこれを行うべきかどうか知りたがっています:

public void button_Click() {
    if(!File.Exists(textBox.Text)) {
        MessageBox.Show("Could not find the file");
        return;
    }

    ProcessFile(textBox.Text); // would have thrown an exception if the file didn't exist
}

ProcessFile が他の種類の Exception をスローする場合を除いて、それは問題ありませんが、それは処理されません。

あなたはこれを行うことができます:

public void button_Click() {
    try {
        ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
    } catch(Exception ex) {
        MessageBox.Show(GetUserMessage(ex));
        return;
    }
}

私の意見では、両方を行う方が良いです:

public void button_Click() {
    try {
        if(!File.Exists(textBox.Text)) {
            MessageBox.Show("Could not find the file");
            return;
        }

        ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
    } catch(Exception ex) {
        MessageBox.Show(GetUserMessage(ex));
        return;
    }
}

このようにして、ユーザーがこの時点で行っていたことに関連する最も具体的なメッセージをユーザーに提供できます。たとえば、彼が Excel ファイルを開こうとした場合、「インポートしたい Excel ファイルが見つかりませんでした」と言うことができます。

これは、チェックした時点からファイルを処理しようとした時点までの間にファイルが削除または名前変更された場合にも機能します。

あるいは、これと同様のことを達成することもできます:

public void button_Click() {
    try {
        if(!File.Exists(textBox.Text)) {
            throw new UserException("Could not find the file");
        }

        ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
    } catch(Exception ex) {
        MessageBox.Show(GetUserMessage(ex));
        return;
    }
}

この場合、独自の Exception クラスを作成し、UserExceptionそのメッセージを翻訳せずにそのまま渡します。これにより、メッセージの表示に使用するのと同じコードを再利用できます。

クラスの例外

一部のクラス ライブラリでエラーが発生した場合は、例外をスローする必要があります。例外の目的は、エラーが見過ごされないようにすることです。

たとえば、これは望ましくありません。

class MyFileHandler {
    public void OpenFile(string fileName) {
        if(!File.Exists(fileName)) return;
        // do stuff
    }

    public void DoStuff() {
        // do stuff
    }
}

開発者が電話をかけた場合、myFileHandlerInstance.OpenFile("note.txt")彼はそれが機能していると思います。次のように、ブール値を返すことができます。

class MyFileHandler {
    public bool OpenFile(string fileName) {
        if(!File.Exists(fileName)) return false;
        // do stuff
        return true;
    }

    public void DoStuff() {
        // do stuff
    }
}

しかし今では、開発者がその値をチェックすることに依存しています。これは以前は一般的な方法でしたが、エラーは無視され、見落とされていたため、例外がより適切な方法になりました。

ユーザーに表示するものに関しては、例外メッセージを直接表示するべきではありません。これらのメッセージは、ユーザーではなく開発者を対象としています。次のように、例外オブジェクトを受け取り、最適なメッセージを返すメソッドを提案します。

public string GetUserErrorMessage(Exception ex) {
    if(ex is FileLoadException) {
        var fileLoadException = (FileLoadException)ex;
        return "Sorry but we failed to load the file: " + fileLoadException.FileName;
    }
}

必要に応じて、エラー コードを含む詳細について Exception プロパティを調べることができます。また、実際の例外の詳細を、独自のデバッグ目的で、ユーザーには見えない場所にキャプチャすることをお勧めします。

于 2013-09-28T15:00:59.217 に答える