处理文件未找到异常的正确位置在哪里?(Where is the correct place to handle file not found exceptions?)

编程入门 行业动态 更新时间:2024-10-11 11:24:52
处理文件未找到异常的正确位置在哪里?(Where is the correct place to handle file not found exceptions?)

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

首先我将我的整个方法放在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块,所以我在这个方法中调用了这个方法,因为它更加封装了这种方式。 现在还有两个try-catch块,但是如果将来逻辑更改我可能想要抛出更多不同的异常,这是另一个原因,即在方法本身中保持异常处理而不是在它被调用的地方。我想看看你的意见。

I have method which check for a recorded image name in a database. If there is such I try to load the image with the recorded path. If there isn't I load a default image.

First I had my whole method in a try-catch block where catch(Exception ex) and no matter what was the exception I just returned 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); } }

Then I figured out that sometimes I may have a record in the database but for some reason the file might be missing so I add check for that :

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

Now I need a proper message for this case too. I get to the conclusion that I can either - use several try-catch blocks to handle those parts or throw an exception and handle the exception from where the method is called.

I chose the second option and now the whole code is :

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

And this is where I call the method :

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

I like this better but I can't say exactly why. The general question is - is this correct way to handle exceptions. And the more specific one - in my exact case where is the better place to put the try-catch blocks? It makes sense to me to be in the body of the method itself because that way I won't need to write those try-catch block everywhere I call the method for me it's even more encapsulated this way. Also now there are two try-catch blocks but if in the future the logic changes I might want to throw more different exceptions, which is another reason to keep the exception handling in the method itself rather where it's called but on the other hand... I want to read your opinion.

最满意答案

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

这是您将拥有处理异常所需的最多信息的地方,并且它还可以保持代码依赖性。 如果让异常冒出太多级别,那么更高级别的代码必须知道低级代码的实现细节,这会增加耦合并破坏抽象。

这带来了另一个重要的观点:如果您没有足够的信息来处理异常,或者您不知道该怎么做,那么您根本不应该处理异常。 相反,你应该让它冒泡,直到它最终到达可以处理它的代码,或者失败,这是一个全局异常处理程序,它显示错误消息和/或写入日志文件和/或将转储发送回开发人员( s)优雅地结束应用程序之前。 例外不像口袋妖怪; 你不应该抓住他们所有人。 只抓住你知道如何处理的人。 ( 关于全局异常处理的相关阅读。 )

在回答您的具体问题时,“如何处理未找到文件/记录/对象的情况”,答案也相对简单: 始终处理异常

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

所以有什么问题? 一个相对微妙的,被称为竞争条件 。 请参阅,只是因为在尝试访问对象之前确保对象存在,对象仍然可以在您验证其存在的时间与您尝试访问它的时间之间消失。 在伪代码中:

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]条件。

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

In response to your general question, "where is the best place to handle exceptions", the answer is a simple one: always handle exceptions closest to the point where they are raised.

That is where you will have the most information necessary to handle the exception, and it also keeps down code dependencies. If you let the exceptions bubble up too many levels, that higher-level code will have to know the implementation details of the lower-level code, which increases coupling and destroys abstraction.

And that brings us to another important point: if you don't have enough information available to handle the exception, or you don't know what to do, you should not handle the exception at all. Instead, you should let it bubble up until it eventually reaches code that can handle it, or failing that, a global exception handler that displays an error message and/or writes to a log file and/or sends a dump back to the developer(s) before ending the application gracefully. Exceptions are not like Pokemon; you aren't supposed to catch 'em all. Only catch the ones you know how to deal with. (Related reading on global exception handling.)

In response to your specific question, "how do I handle the case where a file/record/object is not found", the answer is also relatively straightforward: always handle the exception.

Checking that the object exists first seems like a good idea at first blush. It seems like defensive programming, not attempting to do something you know will fail. And we all know that defensive programming is a best practice.

So what's the problem? A relatively subtle one, known as a race condition. See, just because you ensure that the object exists before you try to access it, the object could still disappear between the time that you verify its existence and the time that you try to access it. In pseudo-code:

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

Now, of course, you're probably saying to yourself that this sounds like it would be extremely rare. How often is the object really doing to disappear (or you lose the ability to access it) in between executing two lines of code? Well, it's actually not that unlikely. Consider the case where the file is located on a network drive and the network cable suddenly gets unplugged. But even if it is extremely rare, well that's why it's called an exception: it's an exception[ally rare] condition.

So the proper solution here is to just handle the exception, because even if you program defensively, you'll still need to handle the exception to handle race conditions. And we all know that unnecessary code duplication is bad.

更多推荐

本文发布于:2023-07-31 10:38:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1342467.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:未找到   异常   正确   位置   文件

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!