0

プログラミングの経験はあまりありませんがOO、学びたいと思っています。今日は、自分の観察が正しければ、エラー処理のスキルを向上させることができると思う状況になっています。

コードが論理的に2つの部分に分かれているイベントがあります:

private void btnSave_Click(object sender, EventArgs e)
{
    IList<AppConfig> AppConfigs = AppConfigService.All().Where(a => (a.IsActive == true) && (a.ConfigProperty == "MaterialImages")).ToList();
    string ImageNameFilter = txtCode.Text;

    if (!ucFileExplorer.IsSavedImage(AppConfigs, ImageNameFilter))
    {
        MessageBox.Show("Error");
        return;
    }

    if (Save())
    {
        LoadForm<Materials>();
    }
}

2番目の部分はSave()メソッドを呼び出すだけですが、私の質問は最初の部分についてです。そこで、で選択した画像をコピーするメソッドを呼び出します。OpenFileDialogロジック全体は、ファイルの参照用に作成したユーザーコントロールにあります。これは、さまざまな形式で使用するためです。実際に対処する方法は次のとおりです。

public bool IsSavedImage(IList<AppConfig> AppConfigs, string ImageNameFilter)
{
    bool IsCopied = false;
    try
    {
        string imgPath = AppConfigs[0].ConfigValue.ToString();
        File.Copy(selectedFile, imgPath + "\\" + ImageNameFilter + slectedFileName + ".jpeg");
        IsCopied = true;
    }
    catch (IOException copyError)
    {
        MessageBox.Show("Error saving image!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return false;
    }
    return IsCopied;
}

そして、ここから私の質問を始めましょう。ここで句が必要だと思います。try-catchこれは、実際の実行が行われ、正しいステータス(trueまたはfalse)を返すのが簡単になるためです。しかし、実際copyErrorは呼び出し元のメソッド(この場合は私のbtn Clickイベント)で処理する必要があると思います。したがって、2つの質問があります。この例外を処理する正しい方法は何ですか。また、メソッドが呼び出される場所に例外を渡したい場合は、どうすればよいですか。

4

5 に答える 5

4

保存機能でエラーメッセージダイアログを表示しないでください。void return typeを使用して名前を「SaveImage」に変更し、例外を発生させます。呼び出し元には「if」はありませんが、例外が発生した場合にエラーメッセージダイアログを表示するtry-catchブロックがあります。

于 2013-02-27T13:02:32.677 に答える
2

この例外を処理する正しい方法は何ですか

それは本当にあなたのアプリケーションに依存します。一般に、必要な場合(または処理できる場合)に例外を処理します。たとえば、より多くの情報を収集したり、エラーに対応したりできる場所で(エラーメッセージを表示し、ログに記録し、再試行します...)

メソッドが呼び出される場所にそれを渡したい場合、どうすればよいですか?

例外をより高いレベルで処理するだけです。例外は、誰かがキャッチするまで呼び出し元に伝播されるため、便利です。呼び出し元の関数にブロックを挿入するだけtry... catchです(すべての実行パスを考慮するように注意してください。そうしないと、それらを処理する関数が見つからない例外がキャッチされず、プログラムが終了します)。

一般的に言って、私はアプリケーションでエラーを処理する4つの主な方法を覚えています:戻り値(エラーコードまたはブール値)、例外、GetLastError-style(エラーコードをどこかに保存し、プログラマーにそれを取得する関数を呼び出させる)、コールバック(エラーの場合に呼び出される関数)。

しばらくの間、エラーを処理するOOの方法であると言われる例外。しかし、適切に設計されたフレームワークには、イベントハンドラー(結局のところ、コールバックの特殊なケース)もあります。

一般に、優れた設計では1つを選択し、それに固執し、最終的に1つのエラータイプを別のエラータイプに「変換」する必要があります(たとえば、Umar Farooq Khawajaの回答のように、サードパーティコードから例外をキャッチし、それらをコールバックにします)。

于 2013-02-27T13:03:49.830 に答える
2

ユーザーコントロールでイベントを定義し、例外が発生したときにそれを発生させて
から、メインの親からこの例外イベントをサブスクライブし、それに応じて処理することができます。

このようなもの。

public Action<Exception> OnExceptionInUserControl;
public bool IsSavedImage(IList<AppConfig> AppConfigs, string ImageNameFilter)
{
    bool IsCopied = false;
    try
    {
        string imgPath = AppConfigs[0].ConfigValue.ToString();
        File.Copy(selectedFile, imgPath + "\\" + ImageNameFilter + slectedFileName + ".jpeg");
        IsCopied = true;
    }
    catch (IOException copyError)
    {
        OnExceptionInUserControl(copyError);
        return false;
    }
    return IsCopied;
}

メインウィンドウで

userControl.OnExceptionInUserControl += new Action<Exception>(ExceptionEventHandler);
于 2013-02-27T12:59:50.403 に答える
2

実際のエラーチェックはビジネスレイヤーで行う必要があるというdutzuに同意します。さらに、UIコンポーネントまたはフォームでErrorHandlerイベントを公開することをお勧めします。このイベントは、エラー状態が発生したときに発生する必要があります。

このように、エラーイベントハンドラーにエラーハンドラーがアタッチされている場合、それが呼び出され、そのエラーハンドラーは必要に応じて適切なアクションを実行できます。

ErrorEventHandler次のようなデリゲートを定義できます。

public void ErrorEventHandler(object sender, ErrorEventArgs e);

そして、ErrorEventArgs次のようなクラス:

public class ErrorEventArgs : EventArgs
{
    // error info exposed via readonly properties
}

次のように、UIコンポーネント/フォームにエラーイベントを作成できます。

public class UIForm
{
    public event ErrorEventHandler ErrorOccurred;

    protected void RaiseErrorEvent(ErrorEventArgs e)
    {
        ErrorEventHandler eh = ErrorOccurred;

        if (eh != null)
        {
            eh.Invoke(this, e);
        }
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
        IList<AppConfig> AppConfigs = AppConfigService.All().Where(a => (a.IsActive == true) && (a.ConfigProperty == "MaterialImages")).ToList();
        string ImageNameFilter = txtCode.Text;

        try
        {
            if (!ucFileExplorer.IsSavedImage(AppConfigs, ImageNameFilter))
            {
                RaiseErrorEvent(new ErrorEventArgs());
                return;
            }

            if (Save())
            {
                LoadForm<Materials>();
            }
        }
        catch (Exception exception)
        {
            // convert exception to an ErrorEventArgs e here
            RaiseErrorEvent(e);
        }
    }
}
于 2013-02-27T13:06:40.920 に答える
1

これは現在一貫性がないため、この方法では例外をキャッチしません。メソッドは例外のみをキャッチするため、たとえば、キャッチされない(メソッドの呼び出しでもIOExceptionキャッチされない)他の例外がスローされる可能性があります。 。IsSavedImageUnauthorizedAccessException

IOException私が見るもう1つの問題は、例外が発生した場合に常にメッセージボックスを表示することです。ある日、さまざまな方法で例外を処理したい場合があり、コア/ビジネス機能での現在の処理方法を変更したくない場合があるため、この部分を削除します。

たとえば、次のようなものです。

public bool SaveImage(IList<AppConfig> AppConfigs, string ImageNameFilter)
{
    string imgPath = AppConfigs[0].ConfigValue.ToString();
    File.Copy(selectedFile, imgPath + "\\" + ImageNameFilter + slectedFileName + ".jpeg");
}

...

try
{
    xxx.SaveImage(....);
}
catch (UnauthorizedAccessException)
{
    // Message to user that the access is denied?
    ...
}
catch (any exception you can handle properly)
{

}
catch
{
    // Couln't be handled properly, so displays generic error message
    ...
}
于 2013-02-27T13:12:18.977 に答える