使用 try..catch 块捕获 C# 异常
我是 C# 新手,希望更好地了解异常捕获。这些问题可能是愚蠢的菜鸟问题。他们对我很重要,我提前道歉。
例如,在 System.IO Path 类 GetFullPath 中,可以引发五种异常:ArgumentException、SecurityException、ArgumentNullException、NotSupportedException 和 PathTooLongException。我知道必须组织 catch 块,以便首先捕获最具体的异常,最后捕获最一般的异常。
问题一: 当 MSDN 提供有关类可能引发的异常的信息时,我如何知道哪个异常是最具体的,哪个是最不具体的?换句话说,如何根据 MSDN 提供的内容确定从最具体到最不具体的异常顺序?
问题2: 我是否需要明确地捕获所有异常,或者仅使用最常见的异常来捕获所有其他异常?例如,仍然使用 Path 类,我是否需要做...
try { ... }
catch(System.ArgumentNullException ane) { ... }
catch(System.NotSupportedException nse) { ... }
catch(System.IO.PathTooLongException ple) { ... }
catch(System.IO.SecurityException se) { ... }
catch(System.ArgumentException ae) { ... }
或者一个简单的...
catch(System.ArgumentException ae) { ... }
捕获所有异常?
问题3: 在 bool 方法中执行以下操作是否正确的语法结构......
try
{
... ;
return true;
}
catch(System.ArgumentException ae)
{
... ;
return false;
}
I am new to C# and wanted to gain a better understanding of exception catching. These questions may be stupid noob questions. They are important to me and I apologize in advance.
For example, in System.IO Path class, GetFullPath, there are five exceptions that can be thrown: ArgumentException, SecurityException, ArgumentNullException, NotSupportedException, and PathTooLongException. I understand that the catch blocks must be organized so that the most specific exception is caught first and the most general exception is caught last.
Question 1:
When MSDN provides information on the possible exceptions thrown by a class, how do I know which exception is the most specific and which is the least specific? In other words, how do I determine the exception order from most specific to least specific from what MSDN gives me?
Question 2:
Do I need to specifically catch all the exceptions explicitly or will using only the most generaL exception catch all the other exceptions as well? For example, still using the Path class, do I need to do ...
try { ... }
catch(System.ArgumentNullException ane) { ... }
catch(System.NotSupportedException nse) { ... }
catch(System.IO.PathTooLongException ple) { ... }
catch(System.IO.SecurityException se) { ... }
catch(System.ArgumentException ae) { ... }
or will a simple ...
catch(System.ArgumentException ae) { ... }
catch all of the exceptions?
Question 3:
Is it correct syntax structure to do the following in a bool method ...
try
{
... ;
return true;
}
catch(System.ArgumentException ae)
{
... ;
return false;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
问题 1:
在每个异常的 MSDN 文档中,您可以看到其继承链。这会告诉您哪些更具体(在链的越低位置,它们越具体)。
您还可以在 Visual Studio 对象浏览器中查看此信息。
问题 2:
捕获可以采取措施的异常是一种很好的做法。如果你无法合理地处理异常,那就让它冒泡吧。
一般来说,最好先捕获更具体的异常。
您还需要查看不同的继承链并决定要捕获哪些异常。例如,只是这样做:
不会捕获
System.IO.SecurityException
因为System.IO.SecurityException
不继承自System.ArgumentException
。问题 3:
是的,这是有效的语法。
但我不会说这是好的做法。如果这是一个异常情况,最好让异常冒出来。建议的设计将导致异常被忽略,并且针对此方法进行编程的任何人都需要检查返回值(他们可能会忘记)。
Question 1:
In the MSDN documentation for each exception you can see its inheritance chain. This tells you which ones are more specific (the lower down the chain they are they more specific).
You can also see this information in the Visual Studio object browser.
Question 2:
It is good practice to catch the exceptions you can do something about. If you can't reasonably do anything with the exception, let it bubble up.
In general, tt is better to catch more specific exceptions first.
You would also want to look at the different inheritance chains and decide what exceptions you want to catch. For example, just doing:
Will not catch an
System.IO.SecurityException
asSystem.IO.SecurityException
doesn't inherit fromSystem.ArgumentException
.Question 3:
Yes, this is valid syntax.
I wouldn't say good practice though. If this is an exceptional situation, it is better to let the exception to bubble up. The suggested design will cause the exception to be ignored and whoever is programming against this method need to check the return value (which they might forget).
一些准则:
您可以通过查看 MSDN 上异常的继承层次结构来了解异常的“特殊性”。如果它们派生自公共基类,则基类异常不太具体。一个常见的例子是 IOException,它是与 I/O 相关的几个更具体的异常的基类。
您通常不应该捕获 ArgumentException、ArgumentNullException、NotSupportedException 等使用异常。如果抛出这些异常,则表明代码中存在必须修复的错误。这些应该仅由您的“最终捕获”捕获以记录,并可能在关闭应用程序之前格式化错误以便更友好地显示。
回应评论:
事后捕获使用异常来验证输入是一个坏习惯,特别是通过捕获 Exception 来完成(因为这可以掩盖其他意外的异常类型。)最好进行验证提前。不幸的是,这个特定方法 (Path.GetFullPath) 的设计并没有很好地考虑到这些准则,因此您需要处理 ArgumentException、NotSupportedException 和 PathTooLongException 来验证用户输入。您可以在单个 catch 子句中执行此操作,如下所示:
您希望使 try 块内的代码尽可能短,因为您不想无意中抑制除 Path.GetFullPath 可能引发的异常之外的其他使用异常。不过,您实际上可能希望单独处理每个异常,因为您可以利用它们之间的差异向用户提供有关他们做错了什么的有用反馈。
A few guidelines:
You can tell the 'specificity' of exceptions by looking at the inheritance heirarchy of the Exceptions on MSDN. If they derive from a common base class, the base class exception is less specific. A common example is IOException, which is the base class for several more specific exceptions related to I/O.
You should generally never catch usage exceptions like ArgumentException, ArgumentNullException, NotSupportedException, etc. If these are thrown, they indicate bugs in your code that must be fixed. These should only be caught by your 'final catch' to log and perhaps format the error for friendlier display before shutting down the application.
In response to the comment:
Catching a usage exception after the fact to validate input is a bad habit, particularly if done by catching
Exception
(as this can mask other unexpected exception types.) It's much better to validate ahead of time. Unfortunately, this particular method (Path.GetFullPath) was not designed well with those guidelines in mind, so you need to handle ArgumentException, NotSupportedException and PathTooLongException to validate the user input. You can do this in a single catch clause like this:You want to keep the code inside the try block as short as possible, since you don't want to inadvertantly suppress other usage exceptions besides those that can be thrown by Path.GetFullPath. You might actually want to handle each exception separately, though, as you can use the differences between them to give helpful feedback to the user as to what they did wrong.
当您将异常名称指定为 catch(System.ArgumentNullExcpetion) 时,它将仅捕获这些类型。您可以在 msdn 上的异常文档页面上查看继承描述,以查看更通用的异常,您只需要担心这些异常。
您可以捕获最常见的异常,但有时在编码和调试程序时,特定的异常可能更有用,它可以帮助您了解抛出的异常类型。
是的,可以使用该语法。
When you specify the name of the exception as catch(System.ArgumentNullExcpetion) then it will catch only those type. You can check the inheritance description on the exception's document page on msdn to check the more generalised exceptions are and you need worry only about those.
You can catch the most general exception but sometimes the specific ones can be more useful while you are coding and debugging your program and it may help you to know what type of exception was thrown.
Yes, that syntax can be used.
1)大多数情况下你可以通过名字来判断。 (例如,ArgumentNullException 继承自 ArgumentException)。当您无法通过名称辨别时,您可以查看文档或对象浏览器,它应该为您提供继承树。
2)具体抓哪些取决于你的需要。许多人会告诉您,即使获得 ArgumentException 或 ArgumentNullException 也意味着您作为开发人员未能在调用中验证更高层的内容。
3)如果您遇到异常,您通常不想返回任何内容 - 异常本身意味着您的方法无法正确完成,这意味着无论如何您都无法为返回值提供良好的数据。然而,也有例外,所以 YMMV。
1) Mostly you can tell using names. (ArgumentNullException inherits from ArgumentException, for instance). When you can't tell by name, you can look at the documentation or your object browser, and it should give you the inheritance tree.
2) Which ones you catch specifically will depend on your needs. Many would tell you that even getting an ArgumentException or ArgumentNullException means that you, as the developer, have failed to validate things higher up in your call.
3) If you've had an exception, you generally don't want to return anything- the exception itself means that your method failed to complete properly, which means you can't have good data for your return value anyway. There are exceptions to this, however, so YMMV.
1) 任何异常的特定性都基于其来自更通用基类异常的继承层次结构。
2) 您可以使用如下一般的 catch all:
3) 是的,这很好,尽管您可能希望在您已经有了更具体的
ArgumentException
之后,如我的 (2) 答案中所示进行 catch all有。1) The specific-ness of any exception is based on its inheritence hierarchy from more generic base class exceptions.
2) You can use a general catch all as below:
3) Yes, this is fine although you might want to have a catch all as shown in my (2) answer after the more specific
ArgumentException
you already have.