22

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

我发现的只是 Exception 类实现了以下内容

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

因此,我尝试实现这些相同的接口并尝试抛出我自己的自定义异常,但该异常没有派生自用System.Exception。我只是被告知

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

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

4

6 回答 6

24

我认为你的前提是错误的。可能会抛出一个不是从System.Exception. 你只是不能把它扔到 C# 中或在 catch 子句中检查对象。从 C# 规范 (v4.0) 的第 8.10 节开始:

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

一般捕获的示例:

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

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

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

于 2012-09-27T07:01:18.100 回答
10

异常设计指南

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

抛出(C# 参考)

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

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

例外概述

在 .NET Framework 中,异常是从异常类继承的对象

因此,您的异常必须来自System.Exception,但如何在其中组织它取决于您。

于 2012-09-27T03:57:35.837 回答
4

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

于 2012-09-27T03:52:51.757 回答
4

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

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

于 2012-09-27T05:59:28.313 回答
3

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

如果我有这个:

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

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

如果你可以扔任何东西,那么你怎么会有一个可以捕捉所有东西并且仍然可以让你访问抛出的对象的 catch 呢?

你可以拥有这个,它绝对能捕捉到所有东西:

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

但是你已经“丢失”了被抛出的东西。

于 2012-09-27T06:11:41.437 回答
0

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

try
{
}
catch (System.Exception) {}
于 2020-06-08T07:09:13.297 回答