C#异常捕获try catch详细介绍
在C#中,异常处理是通过try、catch、finally和throw语句来实现的,它们提供了一种结构化和可预测的方法来处理运行时错误。
C#异常基本用法
try块
异常处理以try块开始,try块包含可能会引发异常的代码。如果在try块中的代码执行过程中发生了异常,控制流将转移到与之匹配的catch块。
try
{// 可能会抛出异常的代码
}
catch块
catch块紧随try块之后,用于捕获和处理异常。可以有多个catch块来捕获不同类型的异常,每个catch块只处理特定类型的异常。
catch (SpecificExceptionType ex)
{// 处理特定类型的异常
}
catch (AnotherExceptionType ex)
{// 处理另一种类型的异常
}
catch
{// 捕获所有未被前面的catch块处理的异常
}
每个catch块可以指定一个异常变量来接收异常的详细信息,如消息、堆栈跟踪等。
finally块
finally块是可选的,它无论是否发生异常都会执行。finally块通常用于清理资源,比如关闭文件流、数据库连接等。
finally
{// 清理代码,无论是否发生异常都会执行
}
throw语句
throw语句用于触发异常。你可以重新抛出当前捕获的异常,或者抛出一个新的异常。
throw; // 重新抛出当前异常throw new Exception("New exception message"); // 抛出一个新的异常
自定义异常
你还可以定义自己的异常类,通过继承System.Exception类来实现。
public class MyCustomException : Exception
{public MyCustomException(string message): base(message){}
}
然后,你可以像使用内置异常类型一样使用你的自定义异常类型。
完整的异常处理示例
下面是一个展示了如何使用try、catch、finally和throw的完整示例:
using System;class ExceptionHandlingExample
{static void Main(){try{Console.WriteLine("Enter a number to divide 100: ");int divisor = Convert.ToInt32(Console.ReadLine());int result = 100 / divisor;Console.WriteLine("Result is: " + result);}catch (DivideByZeroException ex){Console.WriteLine("Cannot divide by zero. Please try again.");}catch (FormatException ex){Console.WriteLine("That's not a valid number. Please try again.");}catch (Exception ex){Console.WriteLine($"An unexpected error occurred: {ex.Message}");throw; // 可以选择重新抛出异常}finally{// 这里的代码不管是否发生异常都会执行Console.WriteLine("Thanks for using our program.");}}
}
在这个例子中,程序尝试将100除以用户输入的数。如果用户输入了非数字或是0,程序将捕获并处理FormatException或DivideByZeroException。无论是否发生异常,finally块都会执行,程序以友好的消息结束。在通用catch块中,异常被重新抛出,这允许异常向上传递,可能被更高级别的异常处理器处理。
异常处理是C#中处理错误的关键部分,能够帮助你创建健壮和易于维护的应用程序。正确使用异常处理能够让你的代码在面对错误时更加优雅地失败,并且提供了足够的信息来帮助调试问题。
自定义异常
在C#中,你可以创建自定义异常以表示应用程序特定的错误情况。自定义异常通常用于提供比标准异常更详细的错误信息或者处理特定于应用程序的错误情况。
要创建自定义异常,你需要从System.Exception类继承,并建议遵循以下步骤:
- 命名自定义异常:异常名称通常以“Exception”结尾。
- 构造函数:提供几个构造函数,至少要提供与基类
Exception相同的四个基本构造函数。 - 序列化支持:如果你的异常类需要在不同的应用程序域之间传递(例如,在远程方法调用中),它必须是可序列化的。(需要标记
[Serializable]属性,并实现序列化接口)
以下是创建自定义异常的示例:
using System;
using System.Runtime.Serialization;[Serializable] // 可序列化
public class MyCustomException : Exception
{// 默认构造函数public MyCustomException(){}// 带错误消息的构造函数public MyCustomException(string message): base(message){}// 带错误消息和内部异常的构造函数(用于异常链)public MyCustomException(string message, Exception innerException): base(message, innerException){}// 实现序列化功能的构造函数protected MyCustomException(SerializationInfo info, StreamingContext context): base(info, context){}// 你可以添加额外的属性和方法来支持你的自定义异常的特殊需求
}
要抛出这个自定义异常,你可以使用throw关键字,像这样:
throw new MyCustomException("This is a custom error message.");
如果你需要在异常中包含更多上下文信息,你可以往自定义异常中添加额外的属性和方法。例如,如果你正在处理与用户账户相关的错误,你的自定义异常可能需要包含一个用户ID或用户名属性。
使用自定义异常的好处是能够清晰地表达发生了什么类型的错误,并且可以携带更多的上下文信息。此外,它们使得错误处理代码更加清晰,因为异常类型直接表明了发生的错误,而不必依赖解析错误消息字符串。记住,你应该只在标准异常不足以表达特定错误情况时创建自定义异常。
throw和throw ex有什么区别
在C#中,throw 和 throw ex 用于抛出异常,但它们的行为有重要差异:
-
throw
- 使用
throw关键字不带任何参数重新抛出当前处理的异常。 - 它保留了原始异常的堆栈跟踪,因此你可以看到异常最初是从哪里抛出的。
try {// 代码可能抛出异常 } catch (Exception) {// 处理异常throw; // 重新抛出当前异常 } - 使用
-
throw ex
- 使用
throw ex重新抛出在catch块中捕获的异常变量ex。 - 这种方式会重置异常的堆栈跟踪,堆栈跟踪将从当前位置开始,而不是最初抛出异常的位置。
- 这通常被认为是一种不良的做法,因为它隐藏了引发异常的原始位置,使得调试更加困难。
try {// 代码可能抛出异常 } catch (Exception ex) {// 处理异常throw ex; // 重新抛出异常,但会丢失原始堆栈跟踪 } - 使用
因此,在大多数情况下,如果你需要在 catch 块中重新抛出异常,应该使用 throw 而不是 throw ex 以保留完整的堆栈信息。保持异常的堆栈跟踪对于诊断问题是非常重要的,因为它显示了异常发生的完整调用序列。
然而,如果你的目的是创建并抛出一个全新的异常(可能会附加一些额外的信息),而不是重新抛出原始异常,那么你会创建一个新的异常实例并使用 throw 关键字抛出它:
try
{// 代码可能抛出异常
}
catch (Exception ex)
{// 创建一个新的异常实例,可能会包含更多信息或者是自定义异常throw new MyCustomException("Additional message", ex);
}
在这种情况下,MyCustomException 将包含一个内部异常 ex,这样你就可以在处理自定义异常的同时,仍然访问到最初异常的信息。
finally和finalize block的区别
在C#中,“finally”块和“finalize”方法是两个不同的概念,它们用于不同的目的。
finally块
finally块是与try和catch块一起使用的,用于确保无论是否发生异常,都会执行一段代码。finally块常用于资源清理工作,比如关闭文件流、数据库连接等。
这里是一个finally块的示例:
using System;
using System.IO;class FinallyExample
{static void Main(){FileStream file = null;try{file = File.Open("example.txt", FileMode.Open);// 执行一些操作}catch (Exception ex){Console.WriteLine(ex.Message);}finally{// 无论是否发生异常,都会执行finally块中的代码if (file != null){file.Close();Console.WriteLine("File stream closed.");}}}
}
在上面的代码中,无论try块中的代码是否成功,或者是否触发了catch块,finally块都会被执行。
finalize方法
finalize方法是一个在对象即将被垃圾回收前执行的清理方法。在C#中,它通过重写Object类的Finalize方法来实现。注意,在.NET中,通常不推荐显式重写Finalize方法,而是建议使用IDisposable接口和Dispose方法来处理资源清理。
这里是一个finalize方法的示例:
using System;class FinalizeExample
{// 析构函数~FinalizeExample(){// 这里是在对象即将被销毁时会执行的代码Console.WriteLine("Finalize method called.");}
}class Program
{static void Main(){FinalizeExample example = new FinalizeExample();// 当example不再被使用时,垃圾回收器在回收之前会调用其Finalize方法example = null;GC.Collect(); // 强制垃圾回收(仅用于示例,通常不建议这么做)GC.WaitForPendingFinalizers(); // 等待所有的Finalizer方法执行完毕}
}
在这个示例中,FinalizeExample类有一个析构函数(在C#中以~开头),这个析构函数就是Finalize方法的语法糖。当垃圾回收器决定回收这个对象的内存时,会自动调用这个析构函数。
总结
finally块是用于异常处理的,确保代码的执行,通常用于释放资源。finalize方法(析构函数)是在对象被垃圾回收前自动调用的,用于执行对象的清理代码。
在实际开发中,finalize方法的使用应该非常谨慎,因为垃圾回收器调用Finalize方法的时间是不确定的。相比之下,IDisposable接口和using语句是更可控、更常见的资源管理机制。
相关文章:
C#异常捕获try catch详细介绍
在C#中,异常处理是通过try、catch、finally和throw语句来实现的,它们提供了一种结构化和可预测的方法来处理运行时错误。 C#异常基本用法 try块 异常处理以try块开始,try块包含可能会引发异常的代码。如果在try块中的代码执行过程中发生了…...
切换阿里云ES方式及故障应急处理方案
一、阿里云es服务相关问题及答解 1.1 ES7.10扩容节点时间 增加节点数量需要节点拉起和数据Rebalance两步,拉起时间7.16及以上的新版本大概10分钟以内,7.16以前大概一小时,数据迁移的时间就看数据量了,一般整体在半小时以内 (需进行相关测试验证) 1.2 ES7.10扩容数据节点…...
CTFhub-RCE-过滤空格
1. 查看当前目录:127.0.0.1|ls 2. 查看 flag_890277429145.php 127.0.0.1|cat flag_890277429145.php 根据题目可以知道空格被过滤掉了 3.空格可以用以下字符代替: < 、>、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等 $IFS在li…...
无需添加udid,ios企业证书的自助生成方法
我们开发uniapp的app的时候,需要苹果证书去打包。 假如申请的是个人或company类型的苹果开发者账号,必须上架才能安装,异常的麻烦,但是有一些app,比如企业内部使用的app,是不需要上架苹果应用市场的。 假…...
【PTA题目】6-20 使用函数判断完全平方数 分数 10
6-20 使用函数判断完全平方数 分数 10 全屏浏览题目 切换布局 作者 张高燕 单位 浙大城市学院 本题要求实现一个判断整数是否为完全平方数的简单函数。 函数接口定义: int IsSquare( int n ); 其中n是用户传入的参数,在长整型范围内。如果n是完全…...
Nas搭建webdav服务器并同步Zotero科研文献
无需云盘,不限流量实现Zotero跨平台同步:内网穿透私有WebDAV服务器 文章目录 无需云盘,不限流量实现Zotero跨平台同步:内网穿透私有WebDAV服务器一、Zotero安装教程二、群晖NAS WebDAV设置三、Zotero设置四、使用公网地址同步Zote…...
一句话总结敏捷实践中不同方法
敏捷实践是指一组优先考虑灵活性、协作和客户满意度的软件开发和项目管理原则和方法。 不同方法论的敏捷实践: 1、敏捷: Sprints:限时迭代(通常 2-4 周),在此期间创建潜在的可交付产品增量。每日站立会议…...
【数据结构】线段树(点修区查)
数据结构-线段树(点修区查) 前置知识 分治递归二叉树 思路 我们需要维护一个支持单点修改,区间查询的数据结构,并且要求在线,一般使用线段树解决。 线段树是一个二叉树形的数据结构。 线段树的思想很简单,…...
Ansys Lumerical | 用于增强现实系统的表面浮雕光栅
在本示例中,我们使用 RCWA 求解器设计了一个斜面浮雕光栅 (SRG),它将用于将光线耦合到单色增强现实 (AR) 系统的波导中。光栅的几何形状经过优化,可将正常入射光导入-1 光栅阶次。 然后我们将光栅特性导出为 Lumerical Sub-Wavelength Model …...
QT day3作业
1.思维导图 2、 完善对话框,点击登录对话框,如果账号和密码匹配,则弹出信息对话框,给出提示”登录成功“,提供一个Ok按钮,用户点击Ok后,关闭登录界面,跳转到其他界面 如果账号和密…...
【Ubuntu】设置永不息屏与安装 dconf-editor
方式一、GUI界面进行设置 No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.6 LTS Release: 20.04 Codename: focal打开 Ubuntu 桌面环境的设置菜单。你可以通过点击屏幕右上角的系统菜单,然后选择设置。在设置菜单中,…...
gRPC 的原理 介绍带你从头了解gRPC
gRPC 的原理 什么是gRPC gRPC的官方介绍是:gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2PB 保…...
Apriori算法
Apriori算法由R. Agrawal和R. Srikant于1994年在数据集中寻找布尔关联规则的频繁项集。该算法的名称是Apriori,因为它使用了频繁项集属性的先验知识。我们应用迭代方法或逐层搜索,其中k-频繁项集用于找到k1个项集。 为了提高频繁项集逐层生成的效率&…...
肖sir__linux讲解(2.1)
linux命令 cp 复制命令 a、cp 原文件名称 新文 件名称(不存在的文件) 案例:cp a k 截图: b.cp 原文件名称 原有文 件名称(存在的文件) 案例:cp a b 截图: c、cp 指定路径复制 格式ÿ…...
The ultimate UI kit and design system for Figma 组件库下载
Untitled UI 是世界上最大的 Figma UI 套件和设计系统。可以启动任何项目,为您节省数千小时,并祝您升级为专业设计师。 采用 100% 自动布局 5.0、变量、智能变体和 WCAG 可访问性精心制作。 900全局样式、变量:超级智能的全局颜色、排版和效…...
Selenium——利用input标签上传文件
Selenium利用input标签上传文件 完整流程 打开文件上传页面选择要上传的文件点击上传按钮确认文件上传成功介绍怎么方便的获取对应元素的Xpath或者Css 简单介绍 在使用Selenium进行浏览器自动化测试时,文件上传是一个常见的需求。而 标签就是实现文件上传功能的…...
C++初阶 日期类的实现(下)
目录 一、输入输出(>>,<<)重载的实现 1.1初始版 1.2友元并修改 1.2.1简单介绍下友元 1.2.2修改 1.3>>重载 二、条件判断操作符的实现 2.1操作符的实现 2.2!操作符的实现 2.3>操作符的实现 2.4>,<,<操作符的实现 三、日期-日期的实现 …...
大师学SwiftUI第16章 - UIKit框架集成
其它相关内容请见虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记 SwiftUI是一套新框架,因此并没有包含我们构建专业应用所需的所有工具。这意味着我们会需要求助于UIKit(移动设备)和AppKit(Mac电脑)等原…...
7.docker运行redis容器
1.准备redis的配置文件 从上一篇运行MySQL容器我们知道,需要给容器挂载数据卷,来持久化数据和配置,相应的redis也不例外。这里我们以redis6.0.8为例来实际说明下。 1.1 查找redis的配置文件redis.conf 下面这个网址有各种版本的配置文件供…...
unity教程
前言 伴随游戏行业的兴起,unity引擎的使用越来越普遍,本文章主要记录博主本人入门unity的相关记录大部分依赖siki学院进行整理。12 一、认识unity引擎? 1、Unity相关信息: Unity的诞生:https://www.jianshu.com/p/550…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...
