c# - 处理文件未找到异常的正确位置在哪里?

标签 c# .net exception error-handling filenotfoundexception

我有一种方法可以检查数据库中记录的图像名称。如果有的话,我会尝试使用记录的路径加载图像。如果没有,我会加载默认图像。

首先,我将整个方法放在 try-catch block 中,其中 catch(Exception ex) 无论异常是什么,我都只返回 Error loading图片 :

    if (File.Exists(imgPath + "\\" + imageName))
    {
        try
        { 
            using (var temp = new Bitmap(imgPath + "\\" + imageName))
            {
                pictureBox1.Image = new Bitmap(temp);
            }

            if (pictureBox1.Image.Width > defaultPicBoxWidth)
            {
                pictureBox1.Width = defaultPicBoxWidth;
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex.ToString());
            MessageBox.Show("Error loading image!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

然后我发现有时我可能在数据库中有一条记录但由于某种原因该文件可能丢失所以我添加检查:

if (imageName != null && !File.Exists(imgPath + "\\" + imageName))

现在我也需要针对此案例的正确消息。我得出的结论是,我可以使用多个 try-catch block 来处理这些部分,或者抛出异常并从调用方法的地方处理异常。

我选择了第二个选项,现在整个代码是:

    if (imageName != null && !File.Exists(imgPath + "\\" + imageName))
    {
        throw new FileNotFoundException(); 
    }

    if (File.Exists(imgPath + "\\" + imageName))
    {
        //try
        //{ 
            using (var temp = new Bitmap(imgPath + "\\" + imageName))
            {
                pictureBox1.Image = new Bitmap(temp);
            }

            if (pictureBox1.Image.Width > defaultPicBoxWidth)
            {
                pictureBox1.Width = defaultPicBoxWidth;
            }
        //}
        //catch (Exception ex)
        //{
        //    logger.Error(ex.ToString());
        //    MessageBox.Show("Error loading image!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        //}
    }

这就是我调用方法的地方:

try
                {
                    //The name of the method described above
                    LoadSavedOrDefaultImage(imageInfo, entity.Picture, txtCode.Text, imageLocation);
                }
                catch (FileNotFoundException ex)
                {
                    logger.Error(ex.ToString());
                    MessageBox.Show("Error loading image! The file wasn't found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                catch (Exception ex)
                {
                    LogErrorAndShowMessage(ex, Resources.ERROR_LOAD);
                }

我更喜欢这个,但我不能确切地说出原因。一般的问题是——这是处理异常的正确方法吗?更具体的一个 - 在我的确切情况下,哪里是放置 try-catch block 的更好地方?在方法本身的主体中对我来说很有意义,因为这样我就不需要在我为我调用方法的任何地方编写那些 try-catch block ,它以这种方式更加封装。现在还有两个 try-catch block ,但如果将来逻辑发生变化,我可能想抛出更多不同的异常,这是将异常处理保留在方法本身而不是调用它的地方的另一个原因但另一方面……我想听听您的意见。

最佳答案

  1. 在回答您的一般性问题“哪里是处理异常的最佳位置”时,答案很简单:始终在最接近引发异常的地方处理异常

    这是您将拥有处理异常所需的最多信息的地方,它还可以降低代码依赖性。如果让异常向上冒泡太多层,高层代码将不得不知道底层代码的实现细节,这会增加耦合并破坏抽象。

    这给我们带来了另一个重要的观点:如果您没有有足够的信息来处理异常,或者您不知道该怎么做,那么您不应该在全部。相反,您应该让它冒泡,直到它最终到达可以处理它的代码,或者失败时,显示错误消息和/或写入日志文件和/或将转储发送回开发人员的全局异常处理程序( s) 在优雅地结束应用程序之前。异常不像口袋妖怪;你不应该把他们都捕获。只捕获那些你知道如何处理的人。 ( Related reading on global exception handling. )

  2. 针对您的具体问题“我如何处理找不到文件/记录/对象的情况”,答案也相对简单明了:始终处理异常 .

    乍一看,首先检查对象是否存在似乎是个好主意。这似乎是防御性编程,而不是尝试做一些你知道会失败的事情。我们都知道防御性编程是一种最佳实践。

    那么问题是什么?一种相对微妙的情况,称为竞争条件。看,仅仅因为您在尝试访问它之前确保该对象存在,该对象仍然可能在您验证其存在和您尝试访问它之间消失。在伪代码中:

    if (!File.Exists(myFile))
    {
        MessageBox("Sorry buddy, that's a no-go.");
    }
    else
    {
        // Uh-oh! The file got deleted!
        File.Open(myFile);  // fails
    }
    

    现在,当然,您可能会对自己说,这听起来非常罕见。在执行两行代码之间,对象真正消失(或者您失去访问它的能力)的频率是多少?好吧,这实际上并非不可能。考虑文件位于网络驱动器上并且网络电缆突然被拔掉的情况。但即使它 极其罕见,这就是它被称为异常(exception)的原因:它是一种异常(exception)[非常罕见]的情况。

    因此这里正确的解决方案是只处理异常,因为即使您进行防御性编程,您仍然需要处理异常以处理竞争条件。我们都知道不必要的代码重复是不好的。

关于c# - 处理文件未找到异常的正确位置在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15338629/

相关文章:

c# - 工具提示出现在表单/窗口后面! (C#/VS 2008)

java - 使用 Geotools 将修改后的形状内容保存到 PostGIS 失败并出现 NullPointerException

c# - 在 C# 中将命令发送到 cmd 提示符

c# - Power BI Embedded PostImportWithFile 返回 BadRequest

c# - Azure Functions 无法再创建 .NET Framework 运行时

exception - Matlab的内置函数可以抛出哪些异常,有没有权威的引用资料?

.net - 如何使用 Try 和 Catch 在 VB.Net 中重试操作?

c# - 如何获取 ArrayLength 类型表达式的 MemberInfo?

c# - 使用 MySQL 数据库的 C# 数据网格控制

c# - 如何动态调用 TryParse?