我是C#的新手,希望更好地了解异常捕获。这些问题可能是愚蠢的菜鸟问题。它们对我很重要,我提前道歉。
例如,在System.IO Path类GetFullPath中,可以抛出五个异常:ArgumentException,SecurityException,ArgumentNullException,NotSupportedException和PathTooLongException。我知道必须组织catch块,以便首先捕获最具体的异常,最后捕获最常见的异常。
问题1: 当MSDN提供有关类抛出的可能异常的信息时,如何知道哪个异常最具体,哪个异常最少?换句话说,我如何确定从MSDN给我的最具体到最不具体的异常顺序?
问题2: 我是否需要明确地捕获所有异常,或者仅使用最大的generaL异常捕获所有其他异常?例如,仍然使用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;
}
答案 0 :(得分:6)
问题1 :
在每个异常的MSDN文档中,您可以看到其继承链。这告诉你哪些更具体(链条越低,它们就越具体)。
您还可以在Visual Studio对象浏览器中看到此信息。
问题2 :
优良作法是捕捉您可以做的事情。如果你不能合理地做任何事情,那就让它冒泡。
一般来说,tt最好首先捕获更具体的异常。
您还需要查看不同的继承链并确定要捕获的异常。例如,只是做:
catch(System.ArgumentException ae) { ... }
由于System.IO.SecurityException
未从System.IO.SecurityException
继承,因此无法抓住System.ArgumentException
。
问题3 :
是的,这是有效的语法。
我不会说好的做法。如果这是一种特殊情况,最好让异常冒泡。建议的设计将导致异常被忽略,并且任何针对此方法编程的人都需要检查返回值(他们可能会忘记)。
答案 1 :(得分:3)
一些指导原则:
您可以通过查看MSDN上Exceptions的继承层次来判断异常的“特异性”。如果它们派生自公共基类,则基类异常不太具体。一个常见的例子是IOException,它是与I / O相关的几个更具体的异常的基类。
您通常不应该捕获使用异常,如ArgumentException,ArgumentNullException,NotSupportedException等。如果抛出这些异常,它们会指示代码中必须修复的错误。这些应该只能被您的“最终捕获”捕获,以便记录并在关闭应用程序之前格式化错误以便更友好地显示。
回应评论:
在验证输入之后捕获使用异常是一个坏习惯,特别是如果通过捕获Exception
来完成(因为这可以掩盖其他意外的异常类型。)提前验证要好得多。不幸的是,这个特殊的方法(Path.GetFullPath)在设计时没有考虑到这些指南,因此您需要处理ArgumentException,NotSupportedException和PathTooLongException来验证用户输入。您可以在这样的单个catch子句中执行此操作:
try
{
//Call Path.GetFullPath somewhere in here
}
catch (Exception ex)
{
if (ex is ArgumentException || ex is NotSupportedException || ex is PathTooLongException)
{
//Your handling here
}
else
{
throw;
}
}
您希望尽可能缩短try块中的代码,因为除了可以由Path.GetFullPath抛出的异常外,您不希望无意中抑制其他使用异常。实际上,您可能希望单独处理每个异常,因为您可以使用它们之间的差异来向用户提供有关他们做错了什么的有用反馈。
答案 2 :(得分:2)
当您将异常的名称指定为catch(System.ArgumentNullExcpetion)时,它将仅捕获那些类型。您可以在msdn上的异常文档页面上检查继承描述,以检查更通用的异常,您只需要担心这些异常。
您可以捕获最常见的异常,但有时在编写和调试程序时,特定的异常会更有用,它可以帮助您了解抛出的异常类型。
是的,可以使用该语法。
答案 3 :(得分:0)
1)任何异常的具体性都基于其更通用的基类异常的继承层次结构。
2)您可以使用如下所示的常规捕获:
try
{
...
}
catch (System.Exception ex)
{
...
}
3)是的,这很好,尽管你可能希望在你已经拥有的更具体的ArgumentException
之后得到一个全部捕获,如我的(2)回答所示。
答案 4 :(得分:0)
1)大多数情况下,您可以使用名称来判断。 (例如,ArgumentNullException继承自ArgumentException)。如果你不能通过名字来判断,你可以查看文档或对象浏览器,它应该为你提供继承树。
2)你特别注意哪些将取决于你的需求。许多人会告诉你,即使得到ArgumentException或ArgumentNullException,也意味着你作为开发人员未能在你的通话中验证更高的东西。
3)如果您遇到异常,通常不想返回任何内容 - 异常本身意味着您的方法无法正确完成,这意味着您无法获得返回值的良好数据。但是,有一些例外,所以YMMV。