1

我有检查数据库中记录的图像名称的方法。如果有这样的话,我尝试用记录的路径加载图像。如果没有我加载默认图像。正确的地方处理文件没找到异常在哪里?

首先,我有我的整个方法的try-catch块,其中catch(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块,但是如果将来逻辑改变了,我可能想要抛出更多不同的异常,这是保持异常处理在方法本身中的另一个原因,而不是它被调用的地方,但另一方面...想读你的意见。

回答

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 
    } 
    

    现在,当然,你可能会对自己说,这听起来像是非常罕见。在执行两行代码之间,对象实际上多久会消失(或者您失去访问它的能力)?那实际上并不是那么不可能。考虑文件位于网络驱动器并且网络电缆突然拔出的情况。但即使极为罕见,这就是为什么它被称为例外:这是一个例外 [盟友罕见]的情况。

    所以这里的正确解决方案就是处理这个异常,因为即使你防守编程,你仍需要来处理异常来处理竞争条件。我们都知道不必要的代码重复是不好的。

1

你会很满意你的第二个选择。如果你的代码中有一些不太可能导致任何异常的部分(如果有的话),那么你不应该在try-catch中接受它们。
在我看来,只有少数时候只有“单向”来处理异常。有一点很重要,那就是你的代码中的那些部分会受到警惕,这可能会导致你的程序发生故障甚至崩溃。
此外,使用几个try-catch块来捕捉不同的异常也很好。有时候,你有一些例外,你想要平等的特质,而不是进一步区分它们。然而在其他事件中,有一些例外,你根本没有期望,然后你至少可以使用catch(Exception ex) { ... }

也许在MSDN有点帮助你。