为什么引发或捕获的类型必须派生自 System.Exception

Why must a type thrown or caught derive from System.Exception

提问人:Maxim Gershkovich 提问时间:9/27/2012 更新时间:6/8/2020 访问量:13609

问:

因此,出于好奇,我想看看异常类有什么特别之处,允许它与关键字一起使用,而标准类则不能。Throw

我发现 Exception 类实现了以下内容

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

因此,我尝试实现这些相同的接口,并尝试抛出我自己的自定义异常,但无济于事。我只是被告知System.Exception

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

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

C# .NET 异常 编译器错误

评论

0赞 Guillaume 9/27/2012
我认为要找出它是如何工作的,看看 的实现而不是类会更有意义。throwException
0赞 Maxim Gershkovich 9/27/2012
很公平,但老实说,我甚至不知道从哪里开始这样做......

答:

4赞 Jesus Ramos 9/27/2012 #1

该语言用作所有异常的基础。这实质上意味着,如果您这样做,任何可抛出或可捕获的异常都不应出错。这可能是因为使用了类的定义,以便所有异常都遵循相同的接口。由于接口一致,异常会附带堆栈跟踪和有意义的消息(例如),这对于日志记录非常宝贵。System.Exception(Exception)myExcSystem.Exception

10赞 horgh 9/27/2012 #2

例外设计准则

异常是报告错误的标准机制。 应用程序和库不应使用返回代码进行通信 错误。异常的使用增加了一致的框架设计 并允许来自成员(如构造函数)的错误报告,这些成员 不能有返回类型

throw(C# 参考)

引发的异常是其类派生自 System.Exception,如以下示例所示。

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

例外概述

在 .NET Framework 中,异常是从 Exception 类

因此,您的例外必须源自 ,但这取决于您,如何在其中组织它。System.Exception

4赞 phoog 9/27/2012 #3

这是CLS设计者的任意选择。 据推测,他们出于一致性的原因做出了这个选择。C# 遵循 CLS;编译器出于此原因强制执行该要求,而不是出于与 Exception 类型的实现相关的任何技术原因。

CLI 实际上可以抛出任何对象。请参见 http://jilc.sourceforge.net/ecma_p3_cil.shtml#_Toc524462405

3赞 Scott Earle 9/27/2012 #4

每个异常都需要有一个通用基类的一个原因是,您可以在单个 catch 块中捕获每种类型的异常。

如果我有这个:

try
{
    ...
}
catch(Exception ex)
{
    // Handle somehow
}

这将捕获所有异常,并允许我显示它是什么(通过使用)。ex.Message

如果你可以扔任何东西,那么你怎么会有一个可以抓住所有东西的渔获物,同时还能让你接触到扔出的物体?

你可以拥有这个,它绝对可以捕捉到一切:

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

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

评论

1赞 yoel halb 11/13/2013
那么捕获(对象o)呢?在与 c++ 互操作时,这可能还不够,但这不应该成为避免抛出其他东西的理由。
24赞 Mike Zboray 9/27/2012 #5

我认为你的前提是错误的。抛出的对象可能不是派生自 。你不能在 C# 中抛出它,也不能在 catch 子句中检查对象。从 C# 规范 (v4.0) 的第 8.10 节开始:System.Exception

某些编程语言可能支持例外,但事实并非如此 可表示为派生自 System.Exception 的对象,尽管 C# 代码永远不会生成此类异常。一般问题 子句可用于捕获此类例外。因此,一个普遍的陷阱 子句在语义上与指定类型的子句不同 System.Exception,因为前者还可以捕获以下 其他语言。

一般渔获物示例:

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

这在调用非托管代码时尤其重要。

有些类型似乎总是在每种语言中都得到特殊对待。主要是因为它们对系统至关重要。、 、 是 C# 中与语言关键字和 CLR 紧密绑定的特殊类型,因此不能只实现接管其角色的类也就不足为奇了。System.ExceptionSystem.ValueTypeSystem.Delegate

0赞 elle0087 6/8/2020 #6

我解决了添加“系统”作为参考的问题

try
{
}
catch (System.Exception) {}