.net C#程序员必需掌握的异常处理

作者:微信公众号:【架构师老卢】
6-11 16:38
26

概述:尽管我们想编写完美的程序,但有时您需要考虑处理 C# 应用程序中的错误情况。这就是你来到这里的原因:关于在 C# 中尝试 catch 的介绍!在本文中,我将解释如何构建 try catch 块的基础知识以及每个块负责什么。该代码很简单,旨在帮助向使用 C# 的初学者解释一些基本概念。如果这听起来像你,请继续阅读!C 语言中的异常处理概述#让我们面对现实吧:在某些时候,我们的 C# 应用程序和服务中会出现异常。我们不愿承认这一点,但我们必须了解如何应对这一现实。C# 中的异常处理是通过使用所谓的 try/catch 块完成的。因此,在 C# 中尝试 catch 是我们设置代码以具有某种类型的保护

尽管我们想编写完美的程序,但有时您需要考虑处理 C# 应用程序中的错误情况。这就是你来到这里的原因:关于在 C# 中尝试 catch 的介绍!

在本文中,我将解释如何构建 try catch 块的基础知识以及每个块负责什么。该代码很简单,旨在帮助向使用 C# 的初学者解释一些基本概念。如果这听起来像你,请继续阅读!

C#语言中的异常处理概述

让我们面对现实吧:在某些时候,我们的 C# 应用程序和服务中会出现异常。我们不愿承认这一点,但我们必须了解如何应对这一现实。

C# 中的异常处理是通过使用所谓的 try/catch 块完成的。因此,在 C# 中尝试 catch 是我们设置代码以具有某种类型的保护并定义我们想要如何处理这些异常的逻辑的方式。

以下各节将解释两个主要部分,try 和 catch,稍后我们将看到额外的第三个组件,我们可以添加到我们在 C# 中创建的 try catch 块中。您也可以按照此视频了解如何在 C# 中使用 try/catch 块处理异常

try

try 块是我们需要查看的异常处理的第一个重要部分。它的作用是将可能引发异常的代码括起来。通过将代码放在 try 块中,我们确保可以捕获并适当地处理发生的任何异常——但它不是由此块处理的,这个块只是告诉我们将要处理的内容。

try 块使用关键字“try”进行结构,后跟一组大括号,其中包含我们要监视异常的代码。此代码通常被称为“受保护代码”,因为在此块中,我们预计可能会引发异常。下面是 C# 中的 try 块示例:

try  
{  
    // Code that might throw an exception  
    int result = Divide(10, 0);  
    Console.WriteLine("The result is: " + result);  
}

在这个例子中,我们有一个名为“Divide”的函数,它采用两个整数作为参数并尝试执行除法运算。但是,如果第二个参数为零,则会引发除以零的异常。通过将此代码包含在 try 块中,我们可以适当地捕获和处理此异常 - 但我们需要另一个块来实际处理它!这就是我们在下一节中要去的地方!

Catch

catch 块的主要目的是提供一种优雅地处理异常的机制。try 块允许我们定义要保护的内容,catch 块允许我们定义我们将处理的内容以及我们将如何处理它。

当抛出异常时,catch 块允许我们指定响应该异常要采取的操作。这些操作可能包括记录异常、向用户显示错误消息或采取任何其他必要的纠正措施。选择权在您手中!

为了捕获特定类型的异常,我们使用 catch 关键字,后跟我们想要处理的异常类型。这使我们能够以不同的方式处理不同的异常,根据特定的异常类型定制我们的响应。

下面是处理特定异常类型的 catch 块的示例,在本例中为 :DivideByZeroException

try  
{  
    int result = 10 / 0; // This will throw a DivideByZeroException  
}  
catch (DivideByZeroException ex)  
{  
    Console.WriteLine("An error occurred: " + ex.Message);  
}

在此示例中,try 块中的代码尝试将数字 10 除以 0,这将导致 .catch 块捕获此异常并在其块中执行代码,在这种情况下,它只是将错误消息写入控制台,显示异常提供的消息。DivideByZeroException

您还可以使用基异常类或完全省略异常部分来捕获所有(嗯,几乎所有)异常:

try  
{  
}  
catch (Exception ex)  
{  
    // this will catch all catchable exceptions  
}  
  
// OR  
try  
{  
}  
catch  
{  
    // note that we don't have an exception instance in this case!  
}

处理多个异常

如果可以从一段被调用的代码中抛出一个异常,那么很有可能有很多异常可以抛出。因此,通常会遇到在单个尝试块中可能发生多种类型的异常的情况。这些例外可能是由于需要适当处理的不同错误或特殊情况而产生的。在本节中,我将讨论如何使用多个 catch 块或具有多个异常类型的单个 catch 块来处理多个异常。让我们看看如何!

多捕获块方法

处理多个异常时,一种方法是使用多个 catch 块。每个 catch 块负责处理特定类型的异常。通过使用此方法,可以指定单独的代码块,以根据其各自的类型处理不同的异常。

下面是一个示例,演示了多捕获块方法:

try  
{  
    // Code that may throw exceptions  
}  
catch (ArgumentNullException ex)  
{  
    // Handle ArgumentNullException  
}  
catch (DivideByZeroException ex)  
{  
    // Handle DivideByZeroException  
}  
catch (FormatException ex)  
{  
    // Handle FormatException  
}

在上面的示例中,try 块后面的 catch 块将捕获并处理发生的任何事件。同样,catch 块 和 将处理它们各自的异常。

带过滤时的单捕获块

处理多个异常的另一种方法是使用可以处理多个异常类型的单个 catch 块。当您希望以相同的方式处理多个异常而不为每个异常编写单独的捕获块时,此方法非常有用。

下面是一个示例,演示了单捕获块方法:

try  
{  
    // Code that may throw exceptions  
}  
catch (Exception ex) when // look at this fancy keyword!  
(  
    ex is ArgumentNullException ||  
    ex is DivideByZeroException ||   
    ex is FormatException  
)  
{  
    // Handle ArgumentNullException, DivideByZeroException, and FormatException  
}

在上面的示例中,catch 块将处理 try 块中发生的任何 、 或。这是因为我们使用关键字将筛选器放置在异常处理程序上!

我应该注意的是,您可以进行更多的过滤,而不仅仅是使用 when 关键字进行类型检查。您可以检查异常实例的不同属性,并相应地创建筛选器。如果需要按特定异常类型的特定异常消息或错误代码进行筛选,则可以使用关键字进行筛选。when

最后的街区

C# 中的 finally 块用于定义一段代码,无论是否发生异常,该段代码都将始终被执行。其目的是确保始终执行某些任务,例如释放资源或执行清理操作,而不管 try 块的结果如何。

最终块在 try 和 catch 块之后执行,无论是否抛出异常。它用关键字“finally”写成,后跟一组大括号 {}。这些大括号内的任何代码都将在捕获块完成后立即执行。

Finally Block 用例

finally 块的一个常见用例是释放在 try 块中获取的任何资源。这可能包括关闭文件句柄、数据库连接、网络套接字或任何其他需要释放的资源。通过将清理代码放在 finally 块中,可以确保即使在 try 块中引发异常,它也会被执行。

下面是一个示例,演示如何使用 finally 块进行资源清理:

try  
{  
    // Code that could potentially throw an exception  
    // Acquiring resources  
    // Performing operations  
}  
catch(Exception ex)  
{  
    // Exception handling code  
    // Logging or displaying error messages  
}  
finally  
{  
    // Code to release resources  
    // Closing file handles, database connections, etc.  
}

在此示例中,如果在 try 块中抛出异常,则程序流将跳转到 catch 块以处理异常。但是,无论是否抛出异常,finally 块中的代码都将始终在之后执行。这确保了任何获取的资源都得到正确释放,防止资源泄漏并保持程序的稳定性。

最终块的替代方案:IDisposable

在 C# 中尝试 catch 时,我们可以使用的最后一个块非常有用——但 try/catch 语法一开始就已经有点笨拙了。我们想要清理资源是一种常见的模式,如果我们处于防御状态,我们希望确保即使遇到错误情况也能清理它们。

我们可以使用接口和 using 块来帮助支持这一点。因此,不需要 finally 块来清理东西,您可以在实现 .代码将简化为:

public class MyClass : IDisposable  
{  
    public void Dispose()  
    {  
        // **TODO:** do your cleanup... same   
        // stuff that you might have wanted  
        // in your finally block!  
    }  
}  
  
using (Myclass myClass = new())  
{  
    // do stuff with myClass  
}  
  
// dispose runs after we leave the block

在我看来,这比支持清理的整个 try/finally 块要笨拙得多——但当然,这不会捕获错误,只是确保您仍然可以运行清理代码。我们可以通过隐式使用进一步简化这一点,当变量超出范围时,该方法将运行:Dispose()

public void SomeMethod()  
{  
    // implicit using...  
    using Myclass myClass = new();  
  
    // do stuff with myClass  
  
    // dispose runs at the end here since the variable goes out of scope  
}

在 C# 语言中尝试 catch 的注意事项

现在,您已经了解了我们可以在 C# 中使用 try catch 的几种不同方法以及一些不同的用例,让我们来谈谈一些注意事项。我们已经看到了我们必须使用的工具,但一些关于正确使用它们的指南似乎很合适:

  1. 它真的是例外吗?:考虑一下你抓到的异常是否真的是例外。不幸的是,许多库和程序都抛出了异常,这些异常对于应用程序来说并不是真正的异常行为。这可能会使逻辑复杂化并减慢速度。所以如果你不需要扔掉它们,就不要扔。但是您可能还需要捕获它们,因为您不希望整个程序终止。
  2. Catch All vs Catch Specific:许多人不喜欢使用尝试捕获所有异常的 try/catch 块。论点是,您可能正在用毯子处理程序掩盖潜在的问题。然而,绝对有一些情况(其中许多我在专业环境中使用过),我们最好有一个包罗万象的情况。对于它们抛出的错误,我们调用的一些事情超出了我们的控制范围,如果您不需要结束整个应用程序或服务......然后你需要处理它们。
  3. 适当的清理:考虑是否需要最终块之类的东西或使用处置模式。请记住,使用 dispose 模式可以帮助清理代码,但仅此一项并不能防止引发异常。
  4. 日志记录和遥测:在C#中使用try catch时,你不仅要了解恢复模式,还应该考虑是否需要对此错误信息执行某些操作。如果你有一个在生产环境中运行的实时服务,在许多情况下,你会想知道哪里出了问题,什么可以改进。日志记录和遥测可以提供帮助!

总结 Try Catch in C#

现在,您已经有机会了解 C# 中 try catch 的基础知识!我的目的是帮助您熟悉不同块的用途,并介绍了最终块!通过一些基本的代码示例以及编程时要牢记的一些额外注意事项,您就可以开始在代码中捕获异常了!

阅读排行