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

时间:2013-03-11 12:31:23

标签: c# .net exception-handling error-handling filenotfoundexception

我有检查数据库中记录的图像名称的方法。如果有这样的话我尝试用记录的路径加载图像。如果没有我加载默认图像。

首先,我将整个方法放在try-catchcatch(Exception ex)中,无论我刚刚返回的是什么例外Error loading image

    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块来处理这些部分或抛出异常并处理调用该方法的异常。

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

    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块的更好位置是什么?因为这样我就不需要在我为这个方法调用方法的任何地方编写try-catch块,这样就更加封装了。现在还有两个try-catch块但是如果将来逻辑更改我可能想要抛出更多不同的异常,这是另一个原因是在方法本身中保留异常处理而不是在它被调用的地方但另一方面......我想读你的意见。

2 个答案:

答案 0 :(得分:3)

  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
    }
    

    现在,当然,你可能会对自己说这听起来非常罕见。在执行两行代码之间,对象在多长时间内才真正消失(或者你失去了访问它的能力)?嗯,实际上并非那么不可能。考虑文件位于网络驱动器上并且网络电缆突然拔掉的情况。但即使它 非常罕见,这就是为什么它被称为异常:它是异常 [ally rare]条件。

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

答案 1 :(得分:1)

你的第二个选择很顺利。如果您的代码中有部分不太可能导致任何异常(如果有的话),那么您不应该在try-catch中使用它们。 在我看来,只有少数几次只有“单向”来处理异常。重要的是,您的代码部分应该受到保护,这可能会导致程序出现故障甚至崩溃 此外,使用几个try-catch - 块来捕获不同的异常也很好。有时候,有些例外情况是你想要平等的特征,而不是进一步区分它们。然而,在其他情况下,有一些您根本没想到的例外情况,然后您至少可以使用catch(Exception ex) { ... }找到

MSDN进行一点查看可能会对你有所帮助。