.NET编程指南声明我们不应该捕获一般异常。我假设以下代码不是很好,因为一般异常类型catch:
private object CreateObject(string classname)
{
object obj = null;
if (!string.IsNullOrEmpty(classname))
{
try
{
System.Type oType = System.Type.GetTypeFromProgID(customClass);
obj = System.Activator.CreateInstance(oType);
}
catch (Exception ex)
{
Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message);
}
}
return obj;
}
在下面的代码中,我捕获特定的异常但不是所有异常,然后我重新抛出异常,以防异常与非泛型异常。但是,函数“CreateInstance”可能会抛出许多异常(ArgumentNullException,ArgumentException,NotSupportedException,TargetInvocationException,MethodAccessException,MemberAccessException,InvalidComObjectException,MissingMethodException,COMException,TypeLoadException)。
捕获所有其他个别例外是否可以接受?或者有更好的方法吗?
private object CreateObject(string classname)
{
object obj = null;
if (!string.IsNullOrEmpty(classname))
{
try
{
System.Type oType = System.Type.GetTypeFromProgID(customClass);
obj = System.Activator.CreateInstance(oType);
}
catch (NotSupportedException ex)
{
Log.Error("...." + ex.Message);
}
catch (TargetInvocationException ex)
{
Log.Error("...." + ex.Message);
}
catch (COMException ex)
{
Log.Error("...." + ex.Message);
}
catch (TypeLoadException ex)
{
Log.Error("...." + ex.Message);
}
catch (InvalidComObjectException ex)
{
Log.Error("...." + ex.Message);
}
catch (Exception ex)
{
Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message);
throw;
}
}
return obj;
}
答案 0 :(得分:12)
作为一般规则,除非:
,否则不应捕获异常您有一个特殊的例外,您可以处理并执行某些操作。但是,在这种情况下,您应该始终检查您是否应该首先考虑并避免例外。
您位于应用程序的顶层(例如UI),并且不希望将默认行为呈现给用户。例如,您可能需要一个带有“请发送给我们您的日志”样式消息的错误对话框。
在以某种方式处理异常之后重新抛出异常,例如,如果您回滚数据库事务。
在这个例子中你为什么要捕捉所有这些不同的类型?在我看来,你的代码可以只是:
try
{
System.Type oType = System.Type.GetTypeFromProgID(customClass);
return System.Activator.CreateInstance(oType);
}
catch (Exception ex)
{
Log.Error("...." + ex.Message);
//the generic catch is always fine if you then do this:
throw;
}
所以你的问题是规则(3)的一个例子 - 你想记录一个异常,但然后继续并将其抛出。
所有不同的类型都在那里,以便在某些情况下你知道你可以处理(即案例1)。例如,假设您知道有一个可以在COMException
附近运行的非托管呼叫 - 那么您的代码将变为:
try
{
System.Type oType = System.Type.GetTypeFromProgID(customClass);
return System.Activator.CreateInstance(oType);
}
catch (COMException cex)
{ //deal with special case:
return LoadUnmanaged();
}
catch (Exception ex)
{
Log.Error("...." + ex.Message);
//the generic catch is always fine if you then do this:
throw;
}
答案 1 :(得分:9)
在框架的.NET 2+中捕获一般异常是完全可以接受的。
- 编辑
你不会这样做的唯一原因是,如果你能用不同的例外做些不同的事情。如果你打算一直处理它们,只需抓住一般(或你所追求的特定的一个,然后让其他任何东西上升)。
答案 2 :(得分:1)
我认为可以捕获所有异常以拦截问题并向用户显示友好消息而不是一些可怕的堆栈输出。
只要您不只是吞下异常,而是记录它们并在后台适当地做出反应。
答案 3 :(得分:1)
如果您想对不同类型的异常执行特殊操作,请在单独的catch块中捕获它。否则单独记录它们是没有意义的。
答案 4 :(得分:1)
没有严格的规则我们不应该使用一般例外,但指南说,只要我们有一个选项来处理特定类型的异常,我们就不应该使用通用异常。
如果我们确定将以相同的方式处理所有异常,那么请使用泛型异常,否则请查看每个特定异常,并且泛尾应该最后用于某个未知异常。
有时候在您的应用程序中发生任何由于特定异常处理而未在代码中处理的异常,那么您的应用程序可能会崩溃..
因此,更好的方法是处理所有特定的异常,然后为一般异常提供一个角落,以便应用程序保持稳定而不会崩溃..
可以在某处报告或记录那些不需要的通用异常,以便将来版本改进。
答案 5 :(得分:1)
在处理错误时习惯性地捕捉基础Exception
被认为是不好的做法,因为它表明可能缺乏对实际处理内容的理解。当您看到一段代码时,会抓住Exception
的内容,“如果此处出现任何问题,请执行此操作”,其中任何内容都可以从NullReferenceException
到OutOfMemoryException
。< / p>
处理所有错误的危险相同,这意味着您并不关心错误的严重程度或解决错误的方式。 99%的情况下,当我看到代码catch(Exception ex)
时,紧接着是吞下异常的代码,并没有提供实际上为什么语句失败的线索。啊。
错误日志记录的示例显示了使用基本Exception
的正确方法,在您真正希望将所有异常处理相同的情况下,通常在应用程序的顶层,以防止应用程序终止在一个丑陋的混乱中。
答案 6 :(得分:1)
我同意基思的回答。两个代码示例的真正问题是它们可以返回null。您有一个名为CreateObject的方法,它返回一个object类型的实例。该方法由于某种原因失败,例如COMException。然后,两个代码示例都将返回null。调用代码现在负责检查结果与null,否则它将抛出NullReferenceException。
引用Framework Design Guidelines 2nd ed.:
如果会员无法成功做到 它应该如何设计 被认为是执行失败, 并且应该抛出异常。
它没有顾名思义。扔!
基思的代码很好;记录异常并重新抛出是可以的。
这是一种私有方法,因此可以说设计指南不适用。我仍然会在这里应用它们 - 为什么当你可以使用异常处理时,用“if(result == null)”将代码丢弃?