我正在用C#编写一个应用程序,它要求我从用户传入的某些维度动态创建一个Array
对象。Array.CreateInstance()
方法可以抛出(按最后计数)6个不同的异常我想要处理。对于每个例外情况,我都希望通过简单的MessageBox.Show()
和针对特殊情况量身定制的消息通知用户。我不想做的是捕捉一般Exception
类型,因为不这样做是最好的做法。我会尝试捕获ArgumentException
或更具体的内容,但所有异常的唯一常见超类是Exception
。
底线:我正在尝试找出处理这么多不同异常的最佳方法,以及什么是高效且更重要的可维护解决方案。
try
{
data = Array.CreateInstance(TypeHelper.StringToType(cbDataType.SelectedItem.ToString()), dimensions);
}
catch (OutOfMemoryException) { }
catch (NullReferenceException) { }
catch (NotSupportedException) { }
catch (ArgumentNullException) { }
catch (ArgumentOutOfRangeException) { }
catch (ArgumentException) { }
答案 0 :(得分:11)
在该列表中,我认为只有4个例外:
NotSupportedException
ArgumentNullException
ArgumentOutOfRangeException
ArgumentException
另外两个你永远不应该抓住,而且在后来的CLR中,你无法捕捉到OOM情况(如果你需要找出,请考虑MemoryFailPoint。)
深入研究Array.CreateInstance
,我们明白为什么会抛出这四个中的每一个:
NotImplementedException
:你给它的类型不能是一个数组,或者是一个开放的泛型。由于您从固定列表中提取这些数据类型,因此您应该知道先验这些是有效类型。我反对处理这个例外。ArgumentNullException
:你应该确定你传递的所有参数都不是null,因此这种情况永远不会发生,你不应该处理这个异常。ArgumentOutOfRangeException
:其中一个长度小于0,您可以测试先验,因此您不应该处理此异常。ArgumentException
:如果类型无效(您已经确定它有效)或者如果没有足够的长度,您可以测试先验。 / LI>
所以,我建议的代码是:
// 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);
总之,我不会处理任何异常,因为您应该能够阻止所有异常发生,并且您不应该关心无法处理异常的实例。
答案 1 :(得分:2)
查看Array.CreateInstance
ArgumentNullException
,似乎大多数异常都是由于违反前提条件而抛出的,这些是您在调用方法之前可以检查的内容。例如,可以通过确保传递的参数不为空来阻止NotSupportedException
,并且可以通过确保支持您请求的类型来阻止OutOfMemoryException
。由于您似乎有一个包含要使用的类型的组合框,因此这应该非常简单。
似乎无法阻止的唯一例外是{{1}},无论如何你都不应该试图抓住它。
答案 2 :(得分:0)
我想你会对基本的Exception类型做一些反思,试图获取特定的消息:
// 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;
}
}
但是,除了选择字符串消息之外,如果你需要做任何事情,你需要做你在问题中发布的内容,并分别处理每个消息。
虽然,我想你也可以创建一个行动类型词典&lt;&gt;代表们......不确定这是不是代码味道。 ;)
答案 3 :(得分:0)
这里显而易见的答案是在将参数传递到Array.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.
}
}