(delphi11最新学习资料) Object Pascal 学习笔记---第9章第2节(finally代码块)

9.2 finally 代码块

​ 还有第四个用于异常处理的关键字,我已经提到过,但到目前为止还没有使用过,那就是 finallyfinally块用于执行一些应始终执行的操作(通常是清理操作)。事实上,无论是否发生异常,finally 代码块中的语句都会被处理。只有在未出现异常或出现异常并已处理的情况下,才会执行 try 代码块后面的普通代码。换句话说,即使出现异常,finally 代码块中的代码也总是在 try 代码块的代码之后执行。

​ 请看这个方法(ExceptFinally 示例的一部分),它执行一些耗时的操作,并在窗体的标题中显示其状态:

procedure TForm1.BtnWrongClick(Sender: TObject);
var
  I, J: Integer;
begin
  Caption := 'Calculating';
  J := 0;
  // 长时间的(错误的)计算...
  for I := 1000 downto 0 do
    J := J + J div I;
  Caption := 'Finished';
  Show('Total: ' + J.ToString);
end;

​ 由于算法中存在错误(因为变量 I 的值可以达到 0,而且还用于除法),程序会中断,但不会重置窗体标题。这就是 try-finally 块的作用:

procedure TForm1.BtnTryFinallyClick(Sender: TObject);
var
  I, J: Integer;
begin
  Caption := 'Calculating';
  J := 0;
  try
    // 长时间的(错误的)计算...
    for I := 1000 downto 0 do
      J := J + J div I;
    Show('Total: ' + J.ToString);
  finally
    Caption := 'Finished';
  end;
end;

​ 当程序执行该函数时,无论是否出现(任何类型的)异常,都会重置游标。此版本函数的缺点是无法处理异常。

9.2.1 finallyexcept

​ 耐人寻味的是,在 Object Pascal 语言中,一个 try 代码块后面可以跟一个 Exceptfinally 语句,但不能同时跟这两个语句。鉴于您经常希望同时使用这两个块,典型的解决方案是使用两个嵌套的 try 块,内部块与 finally 语句相关联,外部块与 except 语句相关联,或者根据情况反之亦然。下面是 ExceptFinally 示例中第三个按钮的代码:

procedure TForm1.BtnTryTryClick(Sender: TObject);
var
  I, J: Integer;
begin
  Caption := 'Calculating';
  J := 0;
  try
    try
      // 长时间的(错误的)计算...
      for I := 1000 downto 0 do
        J := J + J div I;
      Show('Total: ' + J.ToString);
    except
      on E: EDivByZero do
      begin
        // 使用新消息重新引发异常
        raise Exception.Create('Error in Algorithm');
      end;
    end;
  finally
    Caption := 'Finished';
  end;
end;
9.2.2 使用 finally代码块恢复光标

try-finally 块的一个常见用例是资源的分配和释放。另一种相关情况是在操作完成后需要重置临时配置,即使该操作引发了异常。

​ 需要还原的临时配置设置的一个例子是沙漏光标,它在长时间操作中显示,并在操作结束后还原为原来的光标。即使代码很简单,也总有可能出现异常,因此应始终使用 try-finally 块。

​ 在 RestoreCursor 应用程序示例(一个 VCL 应用程序,因为 FireMonkey 中的光标管理比较复杂)中,我编写了以下代码,用于保存当前光标,将其临时设置为沙漏光标,并在操作结束时恢复原始光标:

var
  CurrCur := Screen.Cursor;
  Screen.Cursor := crHourGlass;
try
  // 一些耗时操作
  Sleep(5000);
finally
  Screen.Cursor := CurrCur;
end;
9.2.3 使用托管记录恢复光标

​ 要保护资源分配或定义要还原的临时配置,可以使用托管记录来代替显式的 try-finally 块,这需要编译器添加一个固有的 finally 块。这样,即使在定义记录时需要付出一些初始努力,保护资源或恢复配置的代码编写量也会减少。

​ 这是一个托管记录,代表了上一节代码的相同行为,即在 Initialize 方法中将当前游标保存在一个字段中,并在 Finalize 方法中将其重置:

type
  THourCursor = record
  private
    FCurrCur: TCursor;
  public
    class operator Initialize(out ADest: THourCursor);
    class operator Finalize(var ADest: THourCursor);
  end;

class operator THourCursor.Initialize(out ADest: THourCursor);
begin
  ADest.FCurrCur := Screen.Cursor;
  Screen.Cursor := crHourGlass;
end;

class operator THourCursor.Finalize(var ADest: THourCursor);
begin
  Screen.Cursor := ADest.FCurrCur;
end;

一旦定义了这个托管记录:

var
  HC: THourCursor;
// 一些耗时操作
Sleep(5000);

注解:你可以在 Erik van Bilsen 的以下博文中找到更多通过托管记录保护资源的例子: https://blog.grijjy.com/2020/08/03/automate-restorable-operations-with-custom-managed-records/。这是一系列关于托管记录的详细博客的一部分。

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

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

相关文章

复合数据类型

在C语言中,复合数据类型是指那些可以包含多个简单数据类型的数据类型。以下是一些常见的C语言复合数据类型以及相关的例子: 1. 数组(Arrays): 数组是一种可以存储多个相同类型数据的数据结构。例如: #in…

从像素游戏到 3A 大作的游戏引擎/框架

Bevy —— Rust 构建的游戏引擎 Bevy 是一款由 Rust 语言构建且简单明了的数据驱动的游戏引擎,并将永远保持开源且免费。 Mach —— Zig 游戏引擎和图形工具包 Mach 是一个 Zig 游戏引擎和图形工具包,用于构建高性能、真正跨平台、健壮且模块化的游戏&…

日程安排组件DHTMLX Scheduler v7.0新版亮点 - 拥有多种全新的主题

DHTMLX Scheduler是一个类似于Google日历的JavaScript日程安排控件,日历事件通过Ajax动态加载,支持通过拖放功能调整事件日期和时间,事件可以按天、周、月三个种视图显示。 备受关注的DHTMLX Scheduler 7.0版本日前正式发布了,如…

JS原生DOM操作 - 获得元素/网页大小/元素宽高

文章目录 获得元素的方法获取页面元素位置宽高概念方法获得网页/元素宽高clientHeight和clientWidth:scrollHeight和scrollWidth:window.innerWidth:element.style.width: offsetXXX 获得网页元素的宽高和相对父元素位置&#xff…

有道词典网页版接口分析与爬虫研究

说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除 作者:zhu6201976 一、目标站点 有道词典网页版:网易有道 二、目标接口 url:https://dict.youdao.com/jsonapi_s?doctypejson&…

通过8种加锁情况来弄懂加锁对于线程执行顺序的影响

1个资源类对象,2个线程,2个同步方法,第二个线程等待1s后开启。 //资源类 public class Example {//2个同步方法public synchronized void method1(){System.out.println("线程1正在执行...");}public synchronized void method2()…

(2022级)成都工业学院数据库原理及应用实验三:数据定义语言DDL

唉,用爱发电连赞都没几个,博主感觉没有动力了 想要完整版的sql文件的同学们,点赞评论截图,发送到2923612607qq,com,我就会把sql文件以及如何导入sql文件到navicat的使用教程发给你的 基本上是无脑教程了,…

Banana Pi BPI-M7 RK3588开发板运行RKLLM软件堆AI大模型部署

关于Banana Pi BPI-M7 Banana Pi BPI-M7 采用Rockchip RK3588,板载8/16/32G RAM内存和 64/128G eMMC存储,支持无线wifi6和蓝牙5.2。2x2.5G网络端口,1个HDMIout标准 输出口,2x USB3.0,2xTYPE-C,2x MIPI CSI…

Day96:云上攻防-云原生篇Docker安全系统内核版本漏洞CDK自动利用容器逃逸

目录 云原生-Docker安全-容器逃逸&系统内核漏洞 云原生-Docker安全-容器逃逸&docker版本漏洞 CVE-2019-5736 runC容器逃逸(需要管理员配合触发) CVE-2020-15257 containerd逃逸(启动容器时有前提参数) 云原生-Docker安全-容器逃逸&CDK自动化 知识点&#xff1…

Vue3基础语法

在这个章节中&#xff0c;简单的看下Vue3的基础语法&#xff0c;有了这些基础后&#xff0c;对写vue3单页也就没有什么问题了。 模板语法 在写html时&#xff0c;我们希望在某个节点绑定一个动态值时&#xff0c;是使用dom操作执行的&#xff0c;如下&#xff1a; <!DOCT…

(Java)数据结构——排序(第一节)堆排序+PTA L2-012 关于堆的判断

前言 本博客是博主用于复习数据结构以及算法的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 堆排序&#xff08;Heap Sort&#xff09;概念 堆排序是一种基于堆数据结构的排序算法&#xff0c;其核心思想是将待排序的序列构建成一个最大堆&#xff08;或最小…

大模型+交通治理,高德地图“评诊治”系统迎来全新升级

近日&#xff0c;由中国道路交通安全协会主办的第十四届中国国际道路交通安全产品博览会暨公安交警警用装备展(以下简称交博会)在厦门国际会展中心开幕&#xff0c;会上高德地图发布了全新升级的城市交通“评诊治”智能决策SaaS系统&#xff0c;以助力城市交通的可持续、精细化…

spring boot 集成rocketMq + 基本使用

1. RocketMq基本概念 1. NameServer 每个NameServer结点之间是相互独立&#xff0c;彼此没有任何信息交互 启动NameServer。NameServer启动后监听端口&#xff0c;等待Broker、Producer、Consumer连接&#xff0c; 相当于一个路由控制中心。主要是用来保存topic路由信息&#…

知识图谱与人工智能:携手共进

知识图谱与人工智能&#xff1a;携手共进 一、引言&#xff1a;知识图谱与人工智能的融合 在这个数据驱动的时代&#xff0c;知识图谱与人工智能&#xff08;AI&#xff09;之间的融合不仅是技术发展的必然趋势&#xff0c;也是推动各行各业创新的关键。知识图谱&#xff0c;作…

windows下pycharm中配置conda虚拟环境

目录 一&#xff1a;背景 二&#xff1a;安装conda环境 三&#xff1a;pycharm配置环境 四&#xff1a;注意问题 一&#xff1a;背景 在使用python的过程中&#xff0c;我们可能需要在一个windows环境中创建多个版本的python和安装不同的库去做一些开发任务。 使用conda&a…

TQ15EG开发板教程:在MPSOC上运行ADRV9371

首先需要在github上下载两个文件&#xff0c;本例程用到的文件以及最终文件我都会放在网盘里面&#xff0c; 地址放在本文最后。首先在github搜索hdl选择第一个&#xff0c;如下图所示 GitHub网址&#xff1a;https://github.com/analogdevicesinc/hdl/releases 点击releases…

Docker入门实战教程

文章目录 Docker引擎的安装Docker比vm虚拟机快 Docker常用命令帮助启动类命令镜像命令docker imagesdocker searchdocker pulldocker system dfdocker rmi 容器命令redis前台交互式启动redis后台守护式启动Nginx容器运行ubuntu交互式运行tomcat交互式运行对外暴露访问端口 Dock…

Java基础07--多线程-网络编程-Java高级

一、多线程 1.认识多线程 ①线程 ②多线程 2.创建线程方式 ①方式一&#xff1a;继承Thread类 1.让子类继承Thread线程类 2.重写run方法&#xff0c;就是这个线程执行会执行的操作。 3.创建继承Thread的子类对象就代表一个线程 4.启动线程:.start()-自动执行run方法 注意&am…

绝地求生:PUBG×杜卡迪联名上线!参与投稿评论赢取精美好礼

PUBG杜卡迪联名活动游戏内现已正式上线&#xff01;我们诚邀与您一起在开拓未知战场和书写新历史的过程中&#xff0c;与杜卡迪一同实现您的极速梦想&#xff01; 在本次的杜卡迪工坊中&#xff0c;更是包含了具备标志性红色在内的6种颜色供您自由选择&#xff0c;一起自由驰骋…

创作一首音乐需要多长时间?网易云音乐内测AI音乐生成工具『网易天音』

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…
最新文章