C# 有效的异常处理技术
我正在用C#编写一个应用程序,它要求我从用户传入的某些维度动态创建一个C# 有效的异常处理技术,c#,.net,exception-handling,performance,C#,.net,Exception Handling,Performance,我正在用C#编写一个应用程序,它要求我从用户传入的某些维度动态创建一个数组对象。Array.CreateInstance()方法可以抛出(按上次计数)我想要处理的6个不同的异常。对于每个异常,我希望通过一个简单的MessageBox.Show()和一条针对异常情况定制的消息通知用户。我不想做的是捕获常规异常类型,因为最好不要这样做。我会尝试捕获ArgumentException或更具体的内容,但所有异常的唯一公共超类是Exception 底线:我正在试图找出处理如此多不同异常的最佳方法,以及什么
数组对象。Array.CreateInstance()
方法可以抛出(按上次计数)我想要处理的6个不同的异常。对于每个异常,我希望通过一个简单的MessageBox.Show()
和一条针对异常情况定制的消息通知用户。我不想做的是捕获常规异常
类型,因为最好不要这样做。我会尝试捕获ArgumentException
或更具体的内容,但所有异常的唯一公共超类是Exception
底线:我正在试图找出处理如此多不同异常的最佳方法,以及什么是高效的、更重要的是可维护的解决方案
try
{
data = Array.CreateInstance(TypeHelper.StringToType(cbDataType.SelectedItem.ToString()), dimensions);
}
catch (OutOfMemoryException) { }
catch (NullReferenceException) { }
catch (NotSupportedException) { }
catch (ArgumentNullException) { }
catch (ArgumentOutOfRangeException) { }
catch (ArgumentException) { }
该列表中只有4个例外我会考虑:
NotSupportedException
ArgumentNullException
ArgumentOutOfRangeException
ArgumentException
另外两个你永远都不应该捕捉到,而在后面的CLR中,你无法捕捉到OOM的情况(如果你需要了解的话,考虑一下)
深入研究Array.CreateInstance
,我们会发现这四个都会被抛出的原因:
NotImplementedException
:您为其指定的类型不能是数组,也不能是开放泛型。由于您是从固定列表中提取这些数据类型,因此您应该事先知道这些数据类型是有效的类型。我反对处理这个例外情况
ArgumentNullException
:您应该确定您传递的所有参数都不是null,因此这永远不会发生,您不应该处理此异常
ArgumentOutOfRangeException
:其中一个长度小于0,您可以对其进行先验测试,因此不应处理此异常
ArgumentException
:如果类型无效(您已经确定它是有效的),或者如果没有足够的长度(您可以预先测试),则抛出
因此,我建议的代码是:
// code prior to this point ensures cbDataType only has correct types
// and dimensions has at least 1 dimension and is all greater than or equal to 1
data = Array.CreateInstance(
TypeHelper.StringToType(cbDataType.SelectedItem.ToString()),
dimensions);
总之,我不会处理任何异常,因为您应该能够阻止所有异常的发生,并且您不应该关心无法处理异常的实例。我想您应该对基本异常类型进行一些反思,以尝试获取特定的消息:
// somewhere ...
public static IDictionary<Type, string> exceptionMessages;
// in your method ...
try { ... }
catch( Exception ex ) {
var exType = ex.GetType();
if( exceptionMessages.ContainsKey(exType) ) {
MessageBox.Show( exceptionMessages[exType] );
}
else {
throw ex;
}
}
//某处。。。
公共静态索引例外消息;
//在你的方法中。。。
试试{…}
捕获(例外情况除外){
var exType=ex.GetType();
if(exceptionMessages.ContainsKey(exType)){
Show(例外消息[exType]);
}
否则{
掷骰子;
}
}
然而,如果您除了选择字符串消息之外还需要做任何事情,那么您需要做您在问题中发布的事情,并分别处理每个问题
尽管如此,我想您也可以创建一个类型字典来操作委托。。。但不确定这是否是一种代码气味 查看Array.CreateInstance
似乎大多数异常都是由于违反了先决条件而引发的,您可以在调用该方法之前检查这些先决条件。例如,可以通过确保传递的参数不为null来防止ArgumentNullException
,也可以通过确保支持请求的类型来防止NotSupportedException
。因为您似乎有一个包含要使用的类型的组合框,所以这应该非常简单
您似乎无法阻止的唯一异常是OutOfMemoryException
,可以说您无论如何都不应该尝试捕获它。这里的明显答案是在将参数传递到数组之前验证参数。CreateInstance
方法可以在这些异常发生之前避免大多数异常
但是,如果要捕获多个异常类型,则必须使用反射来简化代码。不幸的是(或许是幸运的)catch
块没有被计算在许多可以共享作用域块的C#构造中
try
{
}
catch (Exception caught)
{
Type[] types =
{
typeof(OutOfMemoryException),
typeof(NullReferenceException)
// Continue adding exceptions to be filtered here.
};
if (types.Contains(caught.GetType()))
{
// Handle accordingly.
}
else
{
throw; // Rethrow the exception and preserve stack trace.
}
}
+1参数异常是使用异常,不应被捕获;使用必须由呼叫方保证。如果您使用代码约定来声明和强制使用约束,默认情况下,它将抛出一个不可修补的ContractException,这是不捕获使用异常的进一步原因,因为该模式不会在所有情况下都起作用。使用(捕获的是OutOfMemoryException | |捕获的是NullReferenceException | | |…)
,IDE将允许您拆分多行以获得更好的可读性。当可以抛出多个异常,但不能/不应该处理这些特定异常时,此模式非常有用。