0

我没有太多好的编程经验,OO但我想学习,今天发生了一种情况,我认为如果我的观察正确,我可以提高我的错误处理技能。

我有一个事件,其代码在逻辑上分为两部分:

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>();
    }
}

第二部分只是调用Save()方法,但我的问题是关于第一部分。在那里我调用了一个方法,该方法应该复制用 a 选择的图像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这里的子句,因为这是实际执行发生的地方,并且更容易返回正确的状态(真或假)。但我认为实际copyError应该在调用方法中处理(在这种情况下是我的 btn Click 事件)。所以我有两个问题,处理这个异常的正确方法是什么,如果我想将它传递到调用方法的地方我该怎么做?

4

5 回答 5

4

不要在保存功能中显示错误消息对话框。将其重命名为具有 void 返回类型的“SaveImage”并引发异常。调用者中没有“if”,而是一个 try-catch 块,在发生异常时显示错误消息对话框。

于 2013-02-27T13:02:32.677 回答
2

处理此异常的正确方法是什么

这真的取决于您的应用程序;通常,您在需要(或可以!)处理的地方处理异常。例如,在您可以收集更多信息和/或对错误做出反应的地方(显示错误消息、日志、重试...)

如果我想将它传递到调用该方法的地方,我该怎么做?

您只需在更高级别处理异常:异常很方便,因为它们会传播给调用者,直到有人捕获它们。只需在调用函数中插入try... catch块(小心考虑所有执行路径,否则找不到任何处理它们的函数的异常将未被捕获,终止程序)。

一般来说,我记得在应用程序中处理错误的四种主要方法:返回值(错误代码或布尔值)、异常、GetLastError-style(在某处存储错误代码,让程序员调用函数来检索它)、回调(提供发生错误时调用的函数)。

有一段时间,异常被称为处理错误的 OO 方式。但是您现在在精心设计的框架中也有事件处理程序(毕竟是回调的一种特殊情况)。

一般来说,一个好的设计应该选择一个并坚持下去,最终将一种错误类型“转换”为另一种错误类型(例如,从第三方代码中捕获异常并将它们变成回调,如 Umar Farooq Khawaja 的回答)

于 2013-02-27T13:03:49.830 回答
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 回答
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 回答
1

我不会以这种方式捕获异常,因为这目前不一致:您的方法仅捕获IOException异常,因此它可能会抛出永远不会被捕获的其他异常(未捕获IsSavedImage或调用方法),UnauthorizedAccessException例如.

我看到的另一个问题是,如果出现IOException异常,您总是会显示一个消息框。我将删除这部分,因为有一天您可能希望以不同的方式处理异常,并且您不想更改其当前在核心/业务功能中的处理方式。

例如:

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 回答