C# 除了某些场景中的关键异常之外,是否可以接受所有异常?

C# 除了某些场景中的关键异常之外,是否可以接受所有异常?,c#,.net,exception,exception-handling,C#,.net,Exception,Exception Handling,在某些情况下,我只想调用某个方法来做一些工作,而不关心如何处理它可能抛出的所有特定异常。相反,我真正关心的是这个方法是否成功 我将提供一个.NET/C的例子。假设我有一个文件要复制,我真正关心的是复制操作是否成功。如果复制失败,我不关心特定异常是FileNotFoundException还是IOException“磁盘空间不足”异常或其他什么。。。在这种情况下,我的应用程序将正常运行,因为此操作并不重要 因此,如何实现这一点的想法是: 试试看 { //试一试 System.IO.File.Cop

在某些情况下,我只想调用某个方法来做一些工作,而不关心如何处理它可能抛出的所有特定异常。相反,我真正关心的是这个方法是否成功

我将提供一个.NET/C的例子。假设我有一个文件要复制,我真正关心的是复制操作是否成功。如果复制失败,我不关心特定异常是FileNotFoundException还是IOException“磁盘空间不足”异常或其他什么。。。在这种情况下,我的应用程序将正常运行,因为此操作并不重要

因此,如何实现这一点的想法是:

试试看
{
//试一试
System.IO.File.Copy(strFile,strFile+“.new”);
} 
捕获(例外情况除外)
{
//如果出现严重异常,则重试
if(临界(ex))
投掷;
//否则就把木头吞下去。。。
Console.WriteLine(“未能复制文件:+ex.Message”);
}
其中IsCritical(Exception ex)是定义为:

publicstaticbool不重要(异常示例)
{
如果(ex是OutOfMemoryException)返回true;
if(ex为AppDomainUnloadexception)返回true;
如果(ex为BadImageFormatException)返回true;
if(ex为CannotUnloadAppDomainException)返回true;
如果(ex为ExecutionEngineeException)返回true;
如果(ex为InvalidProgrameException)返回true;
if(ex是System.Threading.ThreadAbortException)
返回true;
返回false;
}
这个问题基于以下文章:

其思想是遵循异常处理最佳实践的主要规则: -不重新引用就不要捕获一般异常 -只捕获您知道如何处理的异常(在本例中,我希望以相同的方式处理它们…通过记录并继续应用程序逻辑)


那么,对于给定场景,这是一种好方法吗?如果没有,为什么以及做什么更好?

一般建议不要接受异常的原因是它可以隐藏bug。例如,除了执行
文件.Copy
:您还执行字符串处理(
strFile+“.new”
)。这不能抛出(OOM除外),但如果计算更复杂,您可能隐藏了一个bug

在这种情况下,您可能应该将所有计算移出try块。那么,可以接受任何异常。我有把它们记录下来的习惯,以防尽管很小心,我还是犯了一个错误


不要不必要地吞咽的规则是为了保护开发人员不受其自身易犯错误的影响。如果你确信一切正常,那么你就不需要遵守规则。

这句话让我有点担心

如果复制失败,我不关心特定异常是FileNotFoundException还是IOException“磁盘空间不足”异常或其他什么

与其说是FNF异常,不如说是“磁盘空间不足”等——这些都是您可能不想忽略的异常。原因是,如果没有足够的磁盘空间,理论上,你的应用程序最终会失败。这实际上是您不应该捕获一般异常的主要原因之一,因为您有效地掩盖了这些更大的问题


更一般地说,更具体地回答你的问题,如果你确信它不会对你的应用程序产生任何重大影响,那么抓住一个更一般的例外是完全可以的,正如前面提到的(我再次重申是有充分理由的),不会掩盖任何更大/更严重的问题。

您可以为同一次尝试添加多个catch语句:

try
{
 //code here
}
 catch (FileNotFoundException ex1) 
{
  //Do whatever you want
}
catch (IOException ex2)
{
  //Do whatever you want
}
我建议处理你认为不重要的例外,剩下的一个。 只执行一个
catch(异常er){throw;}


另外,仅针对这两个特定的异常就足以捕获一个
IOException
,因为
IOException
FileNotFountException

的父类,我想您已经回答了自己的问题。这完全取决于您的业务逻辑。但通常情况下,如果我要“吞咽”异常,但只能根据它们的特定类型,就像您刚才用另一种方式所做的那样。

在特定情况下吞咽特定异常是可以的,但实际上这取决于用例

我建议处理异常,您可以为未处理的异常处理和使用事件,并将发生的情况通知用户

从调试的角度来看,这并不重要,只要您有权访问代码,因为您可以在VisualStudio中启用对所有常见运行时异常的中断。(调试->异常->公共语言运行时异常->选中左侧复选框)


我永远不会依赖于关键异常列表,因为您不知道该列表是否完整。

我倾向于说,任何来自您自己没有编写的代码的异常都应该被视为关键异常,因为这意味着抛出错误的系统很可能处于未定义的状态,因此您在该系统上尝试的任何后续操作都不能保证成功

因此,我可能会这样做:

  try 
    {
      System.IO.File.Copy(strFile, strFile + ".new");
     //MyLibrary throws exception clases I defined so I know what they are all about
      MyLibrary.SomeClass.DoSomething(strFile);
    }
    catch(ExceptionTypeIDefinedInMyLibraryWhichIKnowICanSafelyIgnore iex)
    {
      Console.WriteLine("Not to worry: "+ iex.Message);
    }
    catch (Exception ex) 
    {
      //This absolute is not something I can handle. Log it and throw.
      Log(ex); throw;
    }
这样,您就不能忽略关键异常,您只能从您自己的子系统中抛出特定类型的异常,因为您可以控制它们抛出的异常

然而,如果您真的想遵循您演示的模式,我倾向于扭转这种局面,只处理您知道可以处理的异常,并抛出所有其他内容

这样,当一个新的
ohmygodthearezombiesintheserver
异常被添加到BCL时,您就不会被烧死,您永远不知道,它可能会发生

i、 e


如果您希望您的程序不可调试,并且是一个
try 
{
  // try 
  System.IO.File.Copy(strFile, strFile + ".new");
} 
catch (Exception ex) 
{
  // if critical exception then rethrow
  if (ICanHandleThis(ex)) 
  {
   Console.WriteLine("Failed to copy the file: " + ex.Message);
  }
  else
  {
   //step aside and let Dr McNinja deal with it
   throw;
  }     
}

public static bool ICanHandleThis(Exception ex) 
{
 //I don't care about these exceptions, they aren't critical
 //to my application for some reason.
 return (ex is SomeTrivialExceptionTypeIDontCareAbout 
        || ex is SomeOtherIgnorableExceptionType);

}