【问题标题】:Why must a type thrown or caught derive from System.Exception为什么抛出或捕获的类型必须派生自 System.Exception
【发布时间】:2012-09-18 19:00:13
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 我认为要了解它是如何工作的,看看throw 的实现而不是Exception 的类会更有意义。
  • 很公平,但老实说,我什至不知道从哪里开始这样做......

标签: c# .net exception compiler-errors


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    Design Guidelines for Exceptions

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

    throw (C# Reference)

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

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

    Exceptions Overview

    在 .NET Framework 中,异常是继承自 异常类

    因此,您的异常必须源自 System.Exception,但这取决于您如何组织它。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        如果我有这个:

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

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

        如果你可以抛出任何东西,那么你将如何拥有一个可以捕获所有东西并仍然让你访问抛出的对象的catch?

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

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

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

        【讨论】:

        • 那么catch(对象o)呢?在与 c++ 互操作时,这可能还不够,但这不应该成为避免抛出其他东西的理由。
        【解决方案5】:

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

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

        一般捕获的示例:

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

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

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

        【讨论】:

          【解决方案6】:

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

          try
          {
          }
          catch (System.Exception) {}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-07-18
            • 1970-01-01
            • 2021-09-25
            • 2020-01-27
            • 1970-01-01
            • 2011-06-17
            • 2019-02-16
            相关资源
            最近更新 更多