【C# 基础精讲】异常的类型和处理方法

news2025/1/21 3:01:46

在这里插入图片描述

异常(Exception)是在程序执行过程中发生的意外或异常情况,例如除零错误、空引用访问、文件不存在等。在C#及其他编程语言中,异常处理是一种重要的机制,用于捕获和处理程序运行时可能出现的错误,以保证程序的健壮性和稳定性。本文将详细介绍C#中的异常类型、异常处理机制以及最佳实践。

1. 异常类型

在C#中,异常分为两种类型:系统异常和自定义异常。

1.1 系统异常

系统异常是由.NET Framework或C#标准库引发的异常。它们是一些常见的运行时错误,如除以零、空引用访问、数组越界等。以下是一些常见的系统异常:

  • ArithmeticException:算术异常,如除以零。
  • NullReferenceException:空引用异常,当试图在引用为null的对象上调用方法或访问属性时引发。
  • IndexOutOfRangeException:索引越界异常,当数组或集合的索引超出范围时引发。
  • InvalidOperationException:无效操作异常,当执行的操作无效或不合理时引发,如集合为空时调用Remove方法。

1.2 自定义异常

除了系统异常,您还可以根据需要创建自定义异常类,以便在特定情况下引发并捕获异常。自定义异常类通常是从Exception类派生而来,您可以为其添加自定义的属性和方法。

class MyCustomException : Exception
{
    public MyCustomException(string message) : base(message)
    {
    }
}

在程序中,您可以使用throw关键字来引发异常:

if (someCondition)
{
    throw new MyCustomException("This is a custom exception.");
}

2. 异常处理

异常处理是指在程序中检测、捕获和处理异常的过程,以防止程序在遇到错误时崩溃或产生不受控制的行为。在C#中,异常处理主要通过trycatchfinallythrow等关键字来实现。

2.1 try-catch 块

try-catch块用于捕获并处理异常。在try块中编写可能引发异常的代码,然后使用一个或多个catch块来捕获不同类型的异常并进行处理。

try
{
    // 可能引发异常的代码
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("除以零错误:" + ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("发生异常:" + ex.Message);
}

在上述示例中,DivideByZeroException是系统异常的一种,catch块捕获并处理了除以零错误。第二个catch块用于捕获其他类型的异常。

2.2 finally 块

finally块用于在无论是否发生异常的情况下都会执行的代码。通常在finally块中进行清理操作,如关闭文件、释放资源等。

try
{
    // 可能引发异常的代码
}
catch (Exception ex)
{
    Console.WriteLine("发生异常:" + ex.Message);
}
finally
{
    // 清理操作,不管是否发生异常都会执行
}

2.3 throw 关键字

throw关键字用于手动引发异常,您可以使用系统异常类或自定义异常类来引发异常。

if (someCondition)
{
    throw new MyCustomException("This is a custom exception.");
}

2.4 使用 using 语句处理资源

C#中的using语句可用于确保在使用完资源后正确释放它们,以避免资源泄漏。例如,使用StreamReader读取文件时,可以这样处理:

using (StreamReader reader = new StreamReader("file.txt"))
{
    string content = reader.ReadToEnd();
    // 处理文件内容
} // 在此处自动调用 reader.Dispose() 释放资源

3. 异常处理的最佳实践

3.1 不要过度使用异常

异常处理应该用于处理真正的异常情况,而不是用于控制程序流程。过度使用异常会影响程序的性能和可维护性。

3.2 使用特定的异常类型

尽可能使用特定的异常类型来捕获和处理异常,这样可以更精确地处理不同类型的错误情况。

3.3 不要捕获所有异常

避免在一个大的catch块中捕获所有异常,这会导致不容易定位和解决问题。应根据不同的异常情况提供适当的处理。

3.4 使用 finally 进行资源释放

在使用可能会占用资源的对象(如文件、数据库连接等)时,应使用finally块确保资源在不管是否发生异常的情况下都能被释放。

3.5 记录异常信息

捕获到的异常应该至少记录错误信息,以便于调试和故障排除。可以使用日志记录库或输出到控制台。

3.6 自定义异常类

对于特定的业务逻辑或应用,可以创建自定义异常类来提供更有意义的异常信息,方便调试和处理。

3.7 嵌套异常处理

在一些情况下,可以在内部处理异常,然后在外部捕获并记录异常信息。

try
{
    try
    {
        // 可能引发异常的代码
    }
    catch (Exception ex)
    {
        // 内部处理异常
    }
}
catch (Exception ex)
{
    Console.WriteLine("外部捕获异常:" + ex.Message);
}

3.8 全局异常处理

您还可以在应用程序级别设置全局异常处理,以处理未在特定地点捕获的异常。这可以通过订阅AppDomain.CurrentDomain.UnhandledException事件来实现。

class Program
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException += GlobalExceptionHandler;

        try
        {
            // 可能引发异常的代码
        }
        catch (Exception ex)
        {
            Console.WriteLine("发生异常:" + ex.Message);
        }
    }

    static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs e)
    {
        Exception ex = (Exception)e.ExceptionObject;
        Console.WriteLine("全局异常处理:" + ex.Message);
        // 可以在这里记录日志等操作
    }
}

4. 异常处理实例

以下是一个使用异常处理的示例,演示了如何读取文件内容并进行错误处理:

try
{
    using (StreamReader reader = new StreamReader("file.txt"))
    {
        string content = reader.ReadToEnd();
        Console.WriteLine("文件内容:" + content);
    }
}
catch (FileNotFoundException ex)
{
    Console.WriteLine("文件不存在:" + ex.Message);
}
catch (IOException ex)
{
    Console.WriteLine("IO错误:" + ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("发生异常:" + ex.Message);
}
finally
{
    Console.WriteLine("处理结束。");
}

在上述示例中,我们使用了try-catch块来捕获不同类型的异常,处理了文件不存在和IO错误的情况,同时还使用了finally块进行清理操作。

5. 总结

异常处理是编程中的重要部分,用于捕获和处理程序运行时可能发生的错误情况,以确保程序的稳定性和健壮性。在C#中,您可以使用try-catch块、finally块和throw关键字来实现异常处理。通过选择恰当的异常类型、适当的异常处理策略以及遵循最佳实践,您可以提高程序的可靠性和可维护性。同时,了解何时使用自定义异常、全局异常处理和资源释放等技术也是编写高质量代码的重要一环。

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

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

相关文章

939. 最小面积矩形;2166. 设计位集;2400. 恰好移动 k 步到达某一位置的方法数目

939. 最小面积矩形 核心思想:枚举矩形的右边那条边的两个点,并用一个哈希表存储相同纵坐标的最近出现的列的列数,不断更新最近出现的左边那条边。 2166. 设计位集 核心思想:这题主要是时间复杂度的优化,用一个flag来标记当前翻转…

word在页眉页脚添加第几页

如果直接在页脚添加数字,整个文档的页脚会是统一的。 这里我们需要的是每一页按照页码排布的文档,所以首先打开页脚设置: 在插入内选择页脚 在弹出的下拉窗口中选择空白即可 在菜单栏会多出“页眉和页脚”的选项卡,选择其中的页…

使用拦截器+Redis实现接口幂等

文章目录 使用拦截器Redis实现接口幂等1.思路分析2.具体实现2.1 创建redis工具类2.2 自定义幂等注解2.2 自定义幂等拦截器2.3 注入拦截器到容器 3.测试 使用拦截器Redis实现接口幂等 1.思路分析 接口幂等有很多种实现方式,拦截器/AOPRedis,拦截器/AOP本…

以对话为场景本质,AIGC 将如何改变游戏规则

8 月 17 日(本周四),融云直播课从排查问题到预警风险,社交产品如何更好保障体验、留住用户?欢迎点击报名~ 生成式 AI 公司 MosaicML 以约 13 亿美元的价格被大数据巨头 Databricks 收购,这个发生于 6 月底的…

python获取音乐文件

浏览器打开音乐地址 http://www.htqyy.com/top/hot 点击第一首歌曲,会打开新的网页并且可以获取 改歌曲的id,就是url中的33 在播放页面点击F12,打开开发者调试功能 如下图所示,在script脚本中可以获取歌曲的下载数据 host&#…

【DICOM医学影像1】数据格式存储于显示,基本知识科普指南

DICOM(Digital Imaging and Communications in Medicine)数据格式,是医学影像存储中的标准格式。无论是X光、CT,还是MRI等等影像,采集的原理不同,但是存储的格式一般都是统一的。本文就对DICOM文件的图像显…

Hands on RL 之 Deep Deterministic Policy Gradient(DDPG)

Hands on RL 之 Deep Deterministic Policy Gradient(DDPG) 文章目录 Hands on RL 之 Deep Deterministic Policy Gradient(DDPG)1. 理论部分1.1 回顾 Deterministic Policy Gradient(DPG)1.2 Neural Network Difference1.3 Why i…

大模型PEFT技术原理(三):Adapter Tuning及其变体

随着预训练模型的参数越来越大,尤其是175B参数大小的GPT3发布以来,让很多中小公司和个人研究员对于大模型的全量微调望而却步,近年来研究者们提出了各种各样的参数高效迁移学习方法(Parameter-efficient Transfer Learning&#x…

java17新特性+ZGC

ZGC垃圾收集 11引入的追求低延迟的垃圾回收器 1.ZGC的内存布局 1.1 region 和G1一样,也是基于Region的堆内存布局。但是ZGC的Region具有动态性:动态创建、动态销毁、动态数据容量。 1.2 垃圾回收机制 相较于CMS,ZGC只有6个阶段&#xff1…

同步、异步、协程

目录 同步异步https 异步请求: 协程1.为什么会要协程?2.异步的运行流程是什么3.协程的原语操作4.协程的定义?5.调度器的定义?6.调度的策略?7. api封装, hook8.多核的模式?9.协程的性能?10.要有哪些案例?nty_servernty_ mysql_client.cnty_ mysql oper.cnty_ …

Python项目实战:基于napari的3D可视化(点云+slice)

文章目录 一、napari 简介二、napari 安装与更新三、napari【巨巨巨大的一个BUG】四、napari 使用指南4.1、菜单栏(File View Plugins Window Help)4.2、Window:layer list(参数详解)4.3、Window:layer…

city walk结合VR全景,打造新时代下的智慧城市

近期爆火的city walk是什么梗?它其实是近年来备受追捧的城市漫步方式,一种全新的城市探索方式,与传统的旅游观光不同,城市漫步更注重与城市的亲密接触,一步步地感受城市的脉动。其实也是一种自由、休闲的方式&#xff…

vscode搭建java开发环境

一、配置extensions环境变量VSCODE_EXTENSIONS, 该环境变量路径下的存放安装组件: 二、setting配置文件 {"java.jdt.ls.java.home": "e:\\software\\jdk\\jdk17",// java运行环境"java.configuration.runtimes": [{"…

分类预测 | MATLAB实现DRN深度残差网络多输入分类预测

分类预测 | MATLAB实现DRN深度残差网络多输入分类预测 目录 分类预测 | MATLAB实现DRN深度残差网络多输入分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.分类预测 | MATLAB实现DRN深度残差网络多输入分类预测 2.代码说明:MATLAB实现DRN深度残差网络…

信捷 XDH Ethercat A_GearIn指令与轴配置

在前面的文章中描述了A_FOLLOW指令,有时不能满足要求,需要更高级的指令A_GearIn指令。 下面的例子A_GearIn指令和CNT_AB指令 实现手轮动马达动,手轮停马达停,手轮转的快马达也转得快。(手轮输出接到PLC的X0和X1点&am…

【内测】百度AI搜索体验

收到百度搜索AI体验邀请,简单测试了一下,目前支持文案创作,AI绘画等。 文案创作功能还行,绘画功能效果比较差。

【数据库】P4 过滤数据 WHERE

过滤数据 WHERE 简介WHERE 子句操作符检测单个值案例范围值检查 BETWEEN AND空值检查 NULL 简介 数据库表一般包含大量的数据,很少需要检索表中的所有行。我们只检索所需数据需要指定搜索条件(search criteria),搜索条件也称为过滤条件(filter conditio…

【每日一题】617. 合并二叉树

【每日一题】617. 合并二叉树 617. 合并二叉树题目描述解题思路 617. 合并二叉树 题目描述 给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会&#xff…

SpringBoot携带Jre绿色部署项目

文章目录 SpringBoot携带Jre绿色部署运行项目1. 实现步骤2. 自测项目文件目录及bat文件内容,截图如下:2-1 项目文件夹列表:2-2. bat内容 3. 扩展: 1.6-1.8版本的jdk下载 SpringBoot携带Jre绿色部署运行项目 说明: 实…

【数据结构与算法】十大经典排序算法-归并排序

🌟个人博客:www.hellocode.top 🏰Java知识导航:Java-Navigate 🔥CSDN:HelloCode. 🌞知乎:HelloCode 🌴掘金:HelloCode ⚡如有问题,欢迎指正&#…