Don*_*ott 103 c# exception-handling
我遇到了这个MSDN页面,其中说明:
不要故意从您自己的源代码中抛出Exception,SystemException,NullReferenceException或IndexOutOfRangeException.
不幸的是,它没有解释原因.我可以猜出原因,但我希望有更多权威人士可以提供他们的见解.
前两个有一些明显的意义,但后两个看起来像你想要使用的(事实上,我有).
此外,这些是唯一应该避免的例外吗?如果有其他人,他们是什么,为什么他们也应该避免?
pok*_*oke 92
Exception是所有异常的基本类型,因此非常不明确.您不应该抛出此异常,因为它根本不包含任何有用的信息.调用代码捕获异常无法消除故意抛出的异常(来自您的逻辑)与其他完全不受欢迎的系统异常并指出真正的错误.
同样的原因也适用于SystemException.如果查看派生类型列表,可以看到大量具有非常不同语义的异常.
NullReferenceException而且IndexOutOfRangeException是另一种.现在这些是非常具体的例外,所以抛出它们可能没问题.但是,您仍然不想抛出这些,因为它们通常意味着您的逻辑中存在一些实际错误.例如,null引用异常意味着您正在尝试访问对象的成员null.如果你的代码中有可能,那么你应该总是明确地检查null并抛出一个更有用的异常(例如ArgumentNullException).类似地,IndexOutOfRangeException当您访问无效索引时(在数组而不是列表上),会出现s.您应该始终确保首先不要这样做并首先检查例如数组的边界.
还有一些其他例外,比如这两个例子,InvalidCastException或者DivideByZeroException,它们会因代码中的特定错误而抛出,通常意味着您做错了或者您没有先检查一些无效值.通过故意从代码中抛出它们,您只是让调用代码更难以确定它们是否因代码中的某些错误而被抛出,或者仅仅因为您决定在实现中重用它们.
当然,这些规则有一些例外(哈).如果您正在构建可能导致与现有异常完全匹配的异常的内容,则可以随意使用它,尤其是在您尝试匹配某些内置行为时.只需确保选择一种非常具体的异常类型.
通常,除非您找到满足您需求的(特定)异常,否则应始终考虑为特定的预期异常创建自己的异常类型.特别是在编写库代码时,这对于分离异常源非常有用.
Mar*_*ell 36
我怀疑最后2的意图是防止与具有预期意义的内置异常混淆.但是,我认为如果你保留了异常的确切意图:它是正确的throw.例如,如果您正在编写自定义集合,那么使用它似乎是完全合理的IndexOutOfRangeException- 比IMO更清晰,更具体ArgumentOutOfRangeException.虽然List<T>可能选择后者,但BCL(不包括阵列)中至少有 41个地方(反射器礼貌)抛出定制IndexOutOfRangeException- 其中没有一个是"低水平"足以值得特别豁免.所以,是的,我认为你可以公正地说这个指导方针是愚蠢的.同样,NullReferenceException在扩展方法中有用 - 如果要保留以下语义:
obj.SomeMethod(); // this is actually an extension method
Run Code Online (Sandbox Code Playgroud)
抛出一个NullReferenceException当obj为null.
如您所指出,在主题“ 抛出异常时应避免的事情”下的“ 创建和抛出异常”(C#编程指南)中,Microsoft确实确实将异常类型列为不应从您自己的源代码中故意抛出的异常类型。System.IndexOutOfRangeException
相反,在本文(《 C#参考》)中,Microsoft似乎违反了自己的准则。这是Microsoft包含在其示例中的方法:
static int GetNumber(int index)
{
int[] nums = { 300, 600, 900 };
if (index > nums.Length)
{
throw new IndexOutOfRangeException();
}
return nums[index];
}
Run Code Online (Sandbox Code Playgroud)
因此,Microsoft本身并不一致,因为它IndexOutOfRangeException在其文档中证明了throw!
这使我相信,至少对于的情况IndexOutOfRangeException,程序员有时可能会抛出该异常类型,并被认为是可以接受的做法。