C#异常捕获try catch详细介绍

在C#中,异常处理是通过trycatchfinallythrow语句来实现的,它们提供了一种结构化和可预测的方法来处理运行时错误。

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){}
}

然后,你可以像使用内置异常类型一样使用你的自定义异常类型。

完整的异常处理示例

下面是一个展示了如何使用trycatchfinallythrow的完整示例:

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,程序将捕获并处理FormatExceptionDivideByZeroException。无论是否发生异常,finally块都会执行,程序以友好的消息结束。在通用catch块中,异常被重新抛出,这允许异常向上传递,可能被更高级别的异常处理器处理。

异常处理是C#中处理错误的关键部分,能够帮助你创建健壮和易于维护的应用程序。正确使用异常处理能够让你的代码在面对错误时更加优雅地失败,并且提供了足够的信息来帮助调试问题。

自定义异常

在C#中,你可以创建自定义异常以表示应用程序特定的错误情况。自定义异常通常用于提供比标准异常更详细的错误信息或者处理特定于应用程序的错误情况。

要创建自定义异常,你需要从System.Exception类继承,并建议遵循以下步骤:

  1. 命名自定义异常:异常名称通常以“Exception”结尾。
  2. 构造函数:提供几个构造函数,至少要提供与基类Exception相同的四个基本构造函数。
  3. 序列化支持:如果你的异常类需要在不同的应用程序域之间传递(例如,在远程方法调用中),它必须是可序列化的。(需要标记[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#中,throwthrow ex 用于抛出异常,但它们的行为有重要差异:

  1. throw

    • 使用 throw 关键字不带任何参数重新抛出当前处理的异常。
    • 它保留了原始异常的堆栈跟踪,因此你可以看到异常最初是从哪里抛出的。
    try
    {// 代码可能抛出异常
    }
    catch (Exception)
    {// 处理异常throw; // 重新抛出当前异常
    }
    
  2. 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块是与trycatch块一起使用的,用于确保无论是否发生异常,都会执行一段代码。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语句是更可控、更常见的资源管理机制。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于卡尔曼滤波实现行人目标跟踪

目录 1. 作者介绍2. 目标跟踪算法介绍2.1 目标跟踪背景2.2 目标跟踪任务分类2.3 目标跟踪遇到的问题2.4 目标跟踪方法 3. 卡尔曼滤波的目标跟踪算法介绍3.1 所用数据视频说明3.2 卡尔曼滤波3.3 单目标跟踪算法3.3.1 IOU匹配算法3.3.2 卡尔曼滤波的使用方法 3.4 多目标跟踪算法 …

rocketmq 安装dashboard1.0.0 mq消息控制台安装 rocketmq控制台安装 rocketmq-dashboard-1.0.0编译安装

1. 官网: 下载 | RocketMQ 2. dashboard安装包位置: 在连接最下面,点击download.zip即可 3. 需要安装maven, 编译命令: mvn clean install -U -Dmaven.test.skiptrue4. 启动jar: java -jar rocketmq-dashboard-1.0.0.jar &…

在线随机字符串生成工具

具体请前往:在线随机字符串生成器--通过该工具生成动态复杂随机密码,随机字符串等,加密盐等

Leetcode—141.环形链表【简单】

2023每日刷题(三十三) Leetcode—141.环形链表 快慢指针算法思想 关于快慢指针为什么能检测出环,可以这么思考。 假设存在一个环: 慢指针进入环后,快指针和慢指针之间相距为d,每一次移动,d都会缩小1&…

【项目设计】网络版五子棋游戏

文章目录 一、项目介绍1. 项目简介2. 开发环境3. 核心技术4. 开发阶段 二、环境搭建1. 安装 wget 工具2. 更换 yum 源3. 安装 lrzsz 传输工具4. 安装⾼版本 gcc/g 编译器5. 安装 gdb 调试器6. 安装分布式版本控制工具 git7. 安装 cmake8. 安装 boost 库9. 安装 Jsoncpp 库10. 安…

iOS线程

1.任务、线程、队列 每一个要执行的操作都是任务:比如说函数 一个队列中可以放很多个线程,一个线程中有很多个任务 可以这样看:有一个办事所(队列),所里有很多窗口(线程)&#xff0c…

DM8共享集群DSC初始化DB实例报错

DM8共享集群DSC初始化DB实例报错 问题描述 启动dmcss和dmasmsvr服务启动后,初始化DB实例提示如下报错: [dmdbalocalhost DSC0]$ /dmdb8/dmdbms/bin/dminit control/dmdb8/dmdbms/dsc_config/DSC0/dminit.ini initdb V8 db version: 0x7000c file dm.k…

[AI]ChatGPT4 与 ChatGPT3.5 区别有多大

ChatGPT 3.5 注册已经不需要手机了,直接邮箱认证就可以,这可真算是好消息,坏消息是 ChatGPT 4 还是要收费。 那么 GPT-3.5 与 GPT-4 区别有多大呢,下面简单测试一下。 以从 TDengine 订阅数据为例,TDengine 算是不太小…

Appium自动化测试:通过appium的inspector功能无法启动app的原因

在打开appium-desktop程序,点击inspector功能,填写app的配置信息,启动服务提示如下: 报错信息: An unknown server-side error occurred while processing the command. Original error: Cannot start the cc.knowyo…

专业数据标注公司:景联文科技领航数据标注行业,满足大模型时代新需求

随着大模型的蓬勃发展和相关政策的逐步推进,为数据要素市场化配置的加速推进提供了有力的技术保障和政策支持。数据要素生产力度的不断提升,为数据标注产业带来了迅速发展的契机。 根据国家工信安全发展研究中心测算,2022年中国数据加工环节的…

leetcode (力扣) 201. 数字范围按位与 (位运算)

文章目录 题目描述思路分析完整代码 题目描述 给你两个整数 left 和 right ,表示区间 [left, right] ,返回此区间内所有数字 按位与 的结果(包含 left 、right 端点)。 示例 1: 输入:left 5, right 7 输出…

c# 字符串转换为byte

c# 字符串转换为byte using System.Text; class proj {internal static void Main(string[] args){byte[] anew byte[3];Console.WriteLine("打印a");Console.WriteLine("a的长度{0}",a.Length);foreach (byte b in a){ Console.WriteLine(b); }a Encodi…

linux系统环境下mysql安装和基本命令学习

此篇文章为蓝桥云课--MySQL的学习记录 块引用部分为自己的实验部分,其余部分是课程自带的知识,链接如下: MySQL 基础课程_MySQL - 蓝桥云课 本课程为 SQL 基本语法及 MySQL 基本操作的实验,理论内容较少,动手实践多&am…

发现区块链世界的新大门——AppBag.io DApp导航网站全面解析

随着区块链技术的飞速发展,分布式应用(DApp)个充满创新和可能性的领域里,appbag.io DApp导航网站应运而生,为您打开探索区块链世界的新大门。 区块链应用的集大成者 AppBag.io DApp导航网站不仅是一个DApp的集散地&a…

muduo源码剖析之TcpServer服务端

简介 TcpServer拥有Acceptor类,新连接到达时new TcpConnection后续客户端和TcpConnection类交互。TcpServer管理连接和启动线程池,用Acceptor接受连接。 服务端封装 - muduo的server端维护了多个tcpconnection 注意TcpServer本身不带Channel&#xff0…

国民技术Cortex-M0系列单片机IAP升级

考虑到设备部署到现场后有可能需要进行软件升级,之前做过PIC系列单片机的升级,现在想做个国民技术N32G031系列Cortex-M0内核的单片机IAP方案。 因为国民技术系列单片机在很多大程度上都模仿了STM32,所以我想其升级方案极有可能差不多。于是在…

Toolformer论文阅读笔记(简略版)

文章目录 引言方法限制结论 引言 大语言模型在zero-shot和few-shot情况下,在很多下游任务中取得了很好的结果。大模型存在的限制:无法获取最新的信息、无法进行精确的数学计算、无法理解时间的推移等。这些限制可以通过扩大模型规模一定程度上解决&…

视频封面:从视频中提取封面,轻松制作吸引人的视频

在当今的数字时代,视频已成为人们获取信息、娱乐和交流的重要方式。一个吸引人的视频封面往往能抓住眼球,提高点击率和观看率。今天将介绍如何从视频中提取封面,轻松制作吸引人的视频封面。 一、准备素材选择合适的视频片段 首先&#xff0…

ubuntu中用docker部署jenkins,并和码云实现自动化部署

1.部署jenkins docker network create jenkins docker run --name jenkins-docker --rm --detach \--privileged --network jenkins --network-alias docker \--env DOCKER_TLS_CERTDIR/certs \--volume jenkins-docker-certs:/certs/client \--volume jenkins-data:/var/jen…

Java面向对象(高级)-- 单例(Singleton)设计模式

文章目录 一、单例设计模式(1) 设计模式概述(2) 何为单例模式(3) 实现思路(4) 单例模式的两种实现方式1. 饿汉式2. 懒汉式3. 饿汉式 vs 懒汉式 (5) 单例模式的…