C# 中的异常和异常处理

随着程序复杂度的增加,程序在执行过程中发生奇怪事情的可能性会越来越高。

C# 和 .NET CLR 使用异常来表明在程序执行期间发生的一种错误。错误通常是意料之外的问题。

出现异常的原因是多种多样。而我们每次在开发应用程序时,都会认为自己写的程序一定会没有问题,但实时是最后都发生了问题。

我们处理任何运行时发生的错误称为异常处理。

一个健壮的程序,在异常发生时应使用异常处理逻辑显示的去处理它们,以维持应用程序的正常流程。这是编码的一个良好习惯,当然,前提是你得正确的处理异常。

C# 中的异常类  

C# 异常由类表示。C# 中的异常类主要直接或间接派生自 System.Exception 类。从 System.Exception 类派生的一些异常类有 System.ApplicationExceptionSystem.SystemException 类。

System.ApplicationException 类支持应用程序生成的异常。不建议从该类派生自定议异常,除非打算重新引发原始异常。

System.SystemException 类是所有预定义系统异常的基类。因为该类充当各种异常类型的基类,所以也不建议代码抛出该类的异常,也不应处理该类的异常,除非打算重新抛出原始异常。

提供一些从 System.SystemException 类派生的预定义异常类:

System.NullReferenceException - 处理因引用空对象而产生的错误。

System.IndexOutOfRangeException - 处理方法引用超出范围的数组索引时生成的错误。

System.OutOfMemoryException - 处理因可用内存不足而产生的错误。

System.StackOverflowException - 处理堆栈溢出产生的错误。

System.ArgumentException - 处理提供给方法的参数之一无效生产的错误。

System.IO.IOException - 处理 I/O 错误。

System.InvalidCastException - 处理类型转换期间生成的错误。

System.DivideByZeroException - 处理因除以零而产生的错误。

System.ArrayTypeMismatchException - 处理类型与数组类型不匹配时生成的错误。

C# 中处理异常

C# 异常处理基于四个关键字:trycatchfinallythrow

try - try 块标识用于激活特定异常的代码块。后面可以跟一个或多个 catch 块。

catch - 表示异常被捕获,将执行 catch 块。可以在这处理异常、记录或忽略异常。如果有多个 catch 块时,则不允许有相同的异常类型。且 Exception 类型必须放在最后一个 catch 块。

finally - finally 块允许是否抛出异常时执行某些代码。需注意的是:finally 块是可选的,且不允许有多个 finally 块。此外,finally 块不能有 returncontinuebreak 关键,它不会让控制流离开 finally 块。

throw - 抛出异常,或者重新抛出异常。

static void Main(string[] args)
{
    Console.WriteLine(Func());

    Console.ReadKey();
}

private static string Func()
{
    try
    {
        return "执行 catch 块语句。";
        //可能导致异常的代码

    }
    catch (ArgumentNullException e1)
    {
        return e1.Message;
        //处理异常代码
    }
    catch (IndexOutOfRangeException e2)
    {
        return e2.Message;
        //处理异常代码
    }
    catch (Exception e3)
    {
        return e3.Message;
        //处理异常代码
    }
    finally
    {
        Console.WriteLine("执行 finally 块语句。");
        // 要执行的语句,在return 前执行
    }

}

执行 finally 块语句。

执行 catch 块语句。  

异常过滤器

在 C# 6.0 中引入了一个新功能来处理称为异常过滤器的异常。此功能将允许在 catch 块中处理更具体的异常,以便可以编写特定于异常条件的代码。

static void Main(string[] args)
{
    try
    {
        //可能导致异常的代码

    }
    catch (Exception e1) when (e1 is ArgumentException) //when (过滤条件表达式)
    {
        //处理异常代码
    }

    Console.ReadKey();
}

自定义的异常

除了系统预定义的异常类型外,我们可以创建自己的异常类型。

当程序中要捕获特定类型的异常并以不同方式处理它时,创建自己的 C# 自定义异常才能体现出异常的真正用处。它有助于跟踪非常关键的非特定类型的异常。可以更轻松地监控应用程序错误并使用错误监控工具记录它。

使用自定义异常类型,我们可以编写特殊代码来处理该异常,还可以监视我们的应用程序以查找特定类型的异常,并在发生异常时通知相关人员。

自定义 C# 异常类型的好处:

  • 调用代码可以对自定义异常类型进行自定义处理

  • 能够围绕该自定义异常类型进行自定义监控

class Program
{
    static void Main(string[] args)
    {
        try
        {
            //抛出自定义异常
            throw new CustomException("自定义异常");
        }
        catch (Exception ex)
        {
            Console.WriteLine("捕获异常信息:" + ex.ToString());
        }
    }
}
class CustomException : Exception
{
    //继承基类异常
    public CustomException(string message)
    {
        
    }
}

C# 异常记录实践

正确的异常处理对于任何应用程序都至关重要。我们要尽可能仅捕获有必要的代码片段,尽量不要一个大的 try 包住整段代码。

当我们程序出现反应变慢、吞吐量下降,可以检查发生最频繁的Exception ,当然这只是提供其中一种排查方法。

在日常开发中会将异常记录到日志库中,以便查看发生的异常信息。大多使用的组件:NLogSeriloglog4net。这三个都能够将异常记录到文件中。也允许将日志发送到其它目标,如:数据库、Windows 事件查看器、电子邮件或错误监控服务。

应将每个异常都记录下来,这对于发现代码中的问题至关重要。当然,能够尽可能记录上下文详细信息也有助于我们排查异常。比如:用户、关键变量等。

将异常记录到文件中是一个很好的实践,但还是不够,一旦在生产环境中,我们不可能每天登录每台服务器去查看日志文件。这会使得日志文件变成黑洞。

这时错误监控服务提供了一个重要工具。它允许在一个中心位置收集所有的异常。

  • 集中式异常记录

  • 查看和搜索所有服务器和应用程序中的所有异常

  • 唯一标识异常

  • 接收有关新异常或高错误率的电子邮件警报

最后,祝大家学习愉快!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值