为什么抛出或捕获的类型必须派生自System.Exception?

22

只是出于好奇,我想知道异常类有什么特别之处,使其能够与关键字Throw一起使用,而标准类则不行。

我发现异常类实现了以下内容:

public class Exception : System.Object, System.Runtime.Serialization.ISerializable, System.Runtime.InteropServices._Exception
{
}

我尝试实现相同的接口并尝试抛出一个不派生自System.Exception的自定义异常,但都没有成功。 我只是被告知:

被捕获或抛出的类型必须派生自System.Exception

那么这是有什么具体的原因吗?我认为应该有,因为托管语言中很少的选择似乎都是随意的。


我认为要了解它的工作原理,最好看一下throw的实现,而不是Exception类。 - Guillaume
公平的说,但是老实说,我甚至都不知道从哪里开始做起... - Maxim Gershkovich
6个回答

24

我认为你的前提是错误的。可能存在一个对象被抛出,但其并非派生自System.Exception。只是在C#中无法抛出该对象或在catch子句中检查该对象。从C#规范(v4.0)第8.10节:

有些编程语言可能支持不能表示为从System.Exception派生的对象的异常,尽管这种异常永远不会由C#代码生成。可以使用通用catch子句来捕获这样的异常。因此,通用catch子句在语义上与指定类型System.Exception的catch子句不同,因为前者也可以捕获其他语言的异常。

通用catch的示例:

try
{
}
catch (Exception) { } // 'specific' catch
catch { } // 'general' catch

特别是在调用非托管代码时,这一点尤为重要。

每种语言都似乎对某些类型进行特殊处理,主要是因为它们对系统非常基础。 System.ExceptionSystem.ValueTypeSystem.Delegate都是C#中的特殊类型,紧密地绑定到语言关键字和CLR,因此不足为奇,你不能仅实现取代它们角色的类。


10

异常设计准则

异常是报告错误的标准机制。 应用程序和库不应使用返回代码来传达错误。 使用异常添加了一致的框架设计,并允许像构造函数这样无法具有返回类型的成员进行错误报告。

throw(C#参考)

抛出的异常是从System.Exception派生的类的对象,如下面的示例所示。

class MyException : System.Exception {}
// ...
throw new MyException();

异常概述

在.NET框架中,异常是从Exception类继承的对象。

因此,您的异常必须派生自System.Exception,但是它的组织方式由您决定。


4
该语言使用System.Exception作为所有异常的基础。这意味着,任何可抛出或可捕获的异常都不应该在执行(Exception)myExc时出错。这可能是因为System.Exception类的定义被用来使所有异常遵循相同的接口。由于一致的接口,异常会带有堆栈跟踪和有意义的消息(例如),这对于记录非常宝贵。

4
这是CLS设计者的任意选择。他们可能出于一致性的原因做出了这个选择。C#遵循CLS;编译器强制执行此要求,而不是与异常类型的实现相关的任何技术原因。
CLI实际上可以抛出任何对象。请参见http://jilc.sourceforge.net/ecma_p3_cil.shtml#_Toc524462405

3
每个异常都需要有一个通用的基类的原因之一是,这样你就可以在单个catch块中捕获每种类型的异常。
如果我有这个:
try
{
    ...
}
catch(Exception ex)
{
    // Handle somehow
}

这将捕获所有异常,我可以使用 ex.Message 来显示它们。

如果你可以抛出 任何东西,那么你怎么能有一个 catch 语句来捕获所有异常并仍然让你访问被抛出的对象呢?

你可以使用下面的代码,它会捕获绝对所有异常:

try
{
    ...
}
catch
{
    // Handle somehow
}

但是你已经“失去”了被扔掉的东西。

1
那 catch (object o) 呢?在与 C++ 互操作时可能不够用,但这并不是避免抛出其他异常的理由。 - yoel halb

0

我解决了,将“System”添加为引用

try
{
}
catch (System.Exception) {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接