(delphi11最新学习资料) Object Pascal 学习笔记---第9章第6节(嵌套异常和 InnerException机制)

9.6 异常的高级功能

​ 除非你对这门语言已经有了很好的了解,否则第一次阅读这部分内容时最好跳过。在此之前,你可以先阅读下一章,将来再回到这一部分。

​ 在本章的最后一部分,我将介绍一些与异常处理相关的高级主题。我将介绍嵌套异常(RaiseOuterException)和拦截类的异常(RaisingException)。

​ 这些功能在早期版本的 Object Pascal 语言中并不存在,但它们为系统增添了强大的功能。

9.6.1 嵌套异常和 InnerException 机制

​ 如果在异常处理器中引发异常,会发生什么情况?传统的答案是,新的异常将取代现有的异常,这就是为什么通常的做法是至少将错误信息合并在一起,写出这样的代码(缺少任何实际操作,只显示与异常相关的语句):

procedure TFormExceptions.ClassicReraise;
begin
  try
    // Do something...
    raise Exception.Create('Hello');
  except
    on E: Exception do
      // Try some fix...
      raise Exception.Create('Another: ' + E.Message);
  end;
end;

​ 这段代码是 AdvancedExcept 示例的一部分。在调用该方法并处理异常时,你会看到一个包含两个异常信息的单一异常:

procedure TFormExceptions.BtnTraditionalClick(Sender: TObject);
begin
  try
    ClassicReraise;
  except
    on E: Exception do
      Show('Message: ' + E.Message);
  end;
end;

​ 输出结果(非常明显)是:

Message: Another: Hello

​ 现在在Object Pascal中,有了对嵌套异常的全系统支持。 在异常处理程序中,您可以创建并引发一个新的异常,同时仍然保持当前异常对象的活动状态,并将其连接到新的异常。 要做到这一点,Exception类有一个InnerException属性(引用前面的异常)和一个BaseException属性(允许访问系列中的第一个异常),因为异常嵌套可以递归。 这些是Exception类中与嵌套异常管理相关的要素:

type
  Exception = class(TObject)
  private
    FInnerException: Exception;
    FAcquireInnerException: Boolean;
  protected
    procedure SetInnerException;
  public
    function GetBaseException: Exception; virtual;
    property BaseException: Exception read GetBaseException;
    property InnerException: Exception read FInnerException;
    class procedure RaiseOuterException(E: Exception); static;
    class procedure ThrowOuterException(E: Exception); static;
  end;

​ 静态类方法是类方法的一种特殊形式。我们将在第 12 章中解释这一语言特性。

​ 从用户的角度来看,要在保留现有异常的同时引发异常,应调用 RaiseOuterException 类方法(或相同的 ThrowOuterException 方法,后者使用面向 C++ 的命名)。处理类似异常时,可以使用新属性访问更多信息。请注意,您只能在异常处理器中调用 RaiseOuterException,这一点基于源代码文档:

Use this function to raise an exception instance from within an exception handler and you want to “acquire” the active exception and chain it to the new exception and preserve the context. This will cause the FInnerException field to get set with the exception currently in play.

使用此函数从异常处理程序中引发异常实例,并且您希望“获取”活动异常并将其链接到新异常并保留上下文。这将导致 FInnerException 字段设置为当前正在播放的异常。

You should only call this procedure from within an except block where this new exception is expected to be handled elsewhere.

您只应从 except 块中调用此过程,在该块中,此新异常应在其他地方处理。

有关实际示例,请参阅 AdvancedExcept 示例。在这个示例中,我添加了一个以新方式引发嵌套异常的方法(与前面列出的 ClassicReraise 方法相比):

procedure TFormExceptions.MethodWithNestedException;
begin
  try
    raise Exception.Create('Hello');
  except
    Exception.RaiseOuterException(Exception.Create('Another'));
  end;
end;

现在,在这个外部异常的处理器中,我们可以访问两个异常对象(也可以看到调用新的 ToString 方法的效果):

try
  MethodWithNestedException;
except
  on E: Exception do
  begin
    Show('Message: ' + E.Message);
    Show('ToString: ' + E.ToString);
    if Assigned(E.BaseException) then
      Show('BaseException Message: ' + E.BaseException.Message);
    if Assigned(E.InnerException) then
      Show('InnerException Message: ' + E.InnerException.Message);
  end;
end;

该调用的输出结果如下:

Message: Another
ToString: Another
Hello
BaseException Message: Hello
InnerException Message: Hello

​ 有两个相关要素需要注意。首先,在单个嵌套异常的情况下,BaseException 属性和 InnerException 属性都指向同一个异常对象,即原始异常对象。其次,虽然新异常的消息只包含实际消息,但通过调用 ToString,可以访问所有嵌套异常的合并消息,并用 sLineBreak 分隔(如 Exception.ToString 方法的代码所示)。

​ 在这种情况下选择使用换行符会产生奇怪的输出结果,但一旦你知道了它,你就可以按照自己喜欢的方式来格式化它,用你选择的符号替换换行符,或者将它们赋值给字符串列表的 Text 属性。

​ 再举一个例子,让我向你展示引发两个嵌套异常时会发生什么。这个就是新方法:

procedure TFormExceptions.MethodWithTwoNestedExceptions;
begin
  try
    raise Exception.Create('Hello');
  except
    try
      Exception.RaiseOuterException(
        Exception.Create('Another'));
    except
      Exception.RaiseOuterException(
        Exception.Create('A third'));
    end;
  end;
end;

​ 这调用的方法与我们之前看到的方法完全相同,输出结果如下:

Message: A third
ToString: A third
Another
Hello
BaseException Message: Hello
InnerException Message: Another

​ 这一次,BaseException 属性和 InnerException 属性指向了不同的对象,ToString 的输出跨越了三行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/547155.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4.Godot图片素材的获取和编辑

游戏开发中经常遇到图片素材的需求 1. 图片素材的准备 术语:Sprite 精灵,游戏开发中指一张图片来源不明的图片,切勿在商业用途使用,以免引起版权风险。 1. 在学习阶段,可以百度或者从一些资源网站获取,这…

面试题总结:HashMap底层原理

不仅仅是一道题,之后的某一天,它可能是破局的关键。 关于HashMap的知识点有哪些呢?分层次展示 1.基础知识: 存储键值对结构、底层数据结构、红黑树和链表 2.位运算与实现 位运算、put、get方法的实现 3.关于锁 segment锁和桶锁、线…

OpenCV基本图像处理操作(三)——图像轮廓

轮廓 cv2.findContours(img,mode,method) mode:轮廓检索模式 RETR_EXTERNAL :只检索最外面的轮廓;RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;RETR_CCOMP:检索所有的轮廓,并将他们组…

广东莱斯广告,6.8米UV喷印推动粤东喷绘产业升级

广东莱斯广告作为汕头市大型的广告服务运营商,近日迎来了一件值得庆祝的事情:彩神6.8米UV喷印机运行一周年,销售服务商深圳嘉豪总经理李伟特地前来回访。该设备是深圳润天智数字设备股份有限公司开发的全球首台搭载XTRA6800H柯尼卡喷头的设备,设备特点是:1.色彩艳丽;2.超宽喷印…

Suno,属于音乐的ChatGPT时刻来临

AI绘画 AI视频我们见过了,现如今AI都能生成一首音乐,包括编曲,演唱,而且仅需几秒的时间便可创作出两分钟的完整歌曲 相信关注苏音的很大一部分都是从获取编曲或者混音插件来的,现如今AI却能帮你几秒生成曲子 今天就带…

Postgresql源码(125)游标恢复执行的原理分析

问题 为什么每次fetch游标能从上一次的位置继续?后面用一个简单用例分析原理。 【速查】 恢复扫描需要知道当前页面、上一次扫描到的偏移位置、当前页面一共有几条: 当前页面:HeapScanDesc结构中记录了扫到的页面(scan->rs_cb…

计算机网络:数据链路层 - CSMA/CA协议

计算机网络:数据链路层 - CSMA/CA协议 CSMA/CA概述帧间间隔工作原理退避算法虚拟载波监听 CSMA/CA概述 讲解CSMA/CA之前,我们回顾一下CSMA/CD的三个特性: 多址接入MA:多个主机连接在一条总线上,竞争使用总线 载波监听…

2024年主流的java混淆工具有哪些

2024年,主流的Java混淆工具可能会包括: ProGuard:ProGuard 是一个免费的开源 Java 混淆工具,可用于压缩、优化和混淆 Java 字节码。它是Android开发者的首选混淆工具之一,并且在Java应用程序中也得到了广泛应用。 Dex…

Stable Diffusion超详细教程!从0-1入门到进阶

一、本地部署 Stable Diffusion 前言 目前市面上比较权威,并能用于工作中的AI绘画软件其实就两款。一个叫Midjourney(简称MJ),另一个叫Stable-Diffusion(简称SD)。MJ需要付费使用,而SD开源免费…

【洛谷 P8802】[蓝桥杯 2022 国 B] 出差 题解(带权无向图+单源最短路+Dijkstra算法+链式前向星+最小堆)

[蓝桥杯 2022 国 B] 出差 题目描述 A \mathrm{A} A 国有 N N N 个城市,编号为 1 … N 1 \ldots N 1…N 小明是编号为 1 1 1 的城市中一家公司的员工,今天突然接到了上级通知需要去编号为 N N N 的城市出差。 由于疫情原因,很多直达的交…

【GEE实践应用】统计遥感数据像元的观测值数量以及良好观测值数量

下面我们以贵州省毕节市2016年8月1号至2018年7月31号两年间像元的观测值数量以及良好的观测值数量为例,统计结果以图像形式进行输出,如图1所示: // 1. 定义研究区域 var studyArea table;// 获取 Landsat 和 Sentinel-2 数据集 var landsat…

第九届少儿模特明星盛典 全球赛首席体验官『韩嘉滢』精彩回顾

2024年1月30日-2月1日,魔都上海迎来了龙年第一场“少儿形体行业美育春晚”!由IPA模特委员会主办的第九届少儿模特明星盛典全球总决赛圆满收官!近2000名少儿模特选手从五湖四海而来,决战寒假这场高水准,高人气&#xff…

前端上传照片压缩 (适合 vue vant组件的)

为什么要这样做? (减小服务器压力 提升用户体验上传照片和加载照片会变快) 最近有一个需求,通过手机拍照后上传图片到服务器,大家应该都知道,现在的手机像素实在是太高了,随便拍一张都是10M以上…

物联网的核心价值是什么?——青创智通

工业物联网解决方案-工业IOT-青创智通 物联网,这个词汇在当今的科技领域已经变得耳熟能详。但当我们深入探索物联网的核心价值时,我们会发现它远不止是一个简单的技术概念,而是一种能够彻底改变我们生活方式和工作方式的革命性力量。 物联网…

Django之rest_framework(三)

一、GenericAPIView的使用 rest_framework.generics.GenericAPIView 继承自APIVIew,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类 1.1、属性 serializer_class 指明视图使用的序列化器…

JVM之JVM栈的详细解析

Java 栈 Java 虚拟机栈:Java Virtual Machine Stacks,每个线程运行时所需要的内存 每个方法被执行时,都会在虚拟机栈中创建一个栈帧 stack frame(一个方法一个栈帧) Java 虚拟机规范允许 Java 栈的大小是动态的或者是…

npm配置阿里镜像库

1、配置阿里云镜像源 #查看当前使用的镜像地址命令 npm config get registry#设置阿里镜像源 npm config set registry http://registry.npmmirror.com 这里要注意下,之前的镜像源地址 https://registry.npm.taobao.org/ 已经不能用了,这里要更改为新…

Grok-1.5 Vision 预览 将数字世界与物理世界连接起来,首款多模态模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

android 创建module

文章目的: 快速创建module并使用 创建步骤: 1 创建module 2 修改module下的build.gradle文件 3 修改清单文件中MainActivity属性,否则APP会因为有多个启动界面而崩溃 4 在主项目build.gradle引用该object Module 至此,可在APP中…

golang 迷宫回溯算法(递归)

// Author sunwenbo // 2024/4/14 20:13 package mainimport "fmt"// 编程一个函数,完成老鼠找出路 // myMap *[8][7]int 地图,保证是同一个地图,因此是引用类型 // i,j表示对地图的哪个点进行测试 func SetWay(myMap *[8][7]int, …