C#中的异常处理问题try catch finally

 更新时间:2023年11月18日 16:55:09   作者:知更鸟的码  
这篇文章主要介绍了C#中的异常处理问题try catch finally,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

C#中的异常处理是一种检测和处理代码中运行时错误的机制,由try catch和finaly块提供支持。

.NET框架提供了常见异常的内置类。

程序执行期间发生的异常,它们可能是由于逻辑或系统错误引起的。

如果程序员未提供处理这些异常的机制,则.NET运行时环境将提供默认机制,该机制将终止程序执行。 

try..catch..finally

C#提供了三个关键字try,catch和finally,以实现异常处理。

尝试将可能引发异常的语句括起来,而如果存在则catch会处理异常。

finally 可以用于完成任何需要清理的工作。  

try..catch..finally块示例:

try
{
    //可能导致异常的语句
}
catch(Type x)
{
    //处理异常的语句
}
finally
{
    //任何清理代码
}

如果try块内部发生任何异常,则控制权转移到适当的catch块,然后转移到finally块。   

但是在C#中,catch和finally块都是可选的。

try块可以与一个或多个catch块或finally块一起存在,也可以与catch和finally块一起存在。  

如果try块内没有发生异常,则控件直接转移到finally块。可以说,finally块中的语句总是执行的。

请注意,通过使用break,continue,return或goto将控制权从finally块中移出是错误的。  

在C#中,异常不过是Exception类型的对象。Exception 是C#中任何异常的最终基类。

C#本身提供了几个标准异常。甚至用户也可以创建自己的异常类,前提是该异常类应继承自Exception类或Exception类的标准派生类之一,例如DivideByZeroExcpetion到ArgumentException等。  

未捕获的异常

以下程序可以通过编译,但在执行过程中将出现错误。

一个数除零是运行时异常,程序终止并显示错误消息。

当前上下文中任何未捕获的异常都会传播到更高的上下文,并寻找适当的catch块来处理它。

如果找不到任何合适的catch块,.NET运行时的默认机制将终止整个程序的执行。  

using System;  
class MyException  
{  
    public static void Main()  
    {  
        int x = 0;  
        int div = 100/x;  
        Console.WriteLine(div);  
     }  
}

具有异常处理机制的上述程序的修改形式如下:

在这里,我们使用标准异常类DivideByZeroException的对象来处理由除零引起的异常。

using System;
class MyException
{
    public static void Main()
    {
        int x = 0;
        int div = 0;
        try
        {
            div = 100 / x;
            Console.WriteLine("此行未执行");
        }
        catch (DivideByZeroException)
        {
            Console.WriteLine("发生异常");
        }
        Console.WriteLine($"结果为 {div}");
    }
} 

以上代码的结果如下所示:

在上述情况下,程序不会意外终止。

程序控制从try块内发生异常的地方转移到catch块,如果找到任何合适的catch块,则在该catch中执行语句,然后继续正常执行程序语句。  

如果存在以下代码的finally块,则finally块中的代码也将被执行。 

using System;
class MyException  
{
    public static void Main()
    {
        int x = 0;
        int div = 0;
        try
        {
            div = 100/x;
            Console.WriteLine("此行未执行");
        }
        catch(DivideByZeroException)
        {
            Console.WriteLine("发生异常");
        }
        finally
        {
            Console.WriteLine("Finally块");
        }
        Console.WriteLine($"结果为 {div}");
    }
}

请记住,在C#中,catch块是可选的。

以下程序在C#中是完全合法的。

using System;
class MyException  
{
    public static void Main()
    {
        int x = 0;
        int div = 0;
        try
        {
            div = 100/x;
            Console.WriteLine("此行未执行");
        }
        finally
        {
            Console.WriteLine("Finally块");
        }
        Console.WriteLine($"结果为 {div}");
    }
}

但是在这种情况下,由于没有异常处理catch块,因此执行将终止。

但是在终止程序语句之前,finally块中的语句将得到执行。

在C#中,try块之后必须是catch或finally块。  

多个catch块 

一个try块可以引发多个异常,可以使用多个catch块来处理。

记住,在通用的catch 块之前应该有更专业的catch 块。否则,编译器将显示编译错误。 

using System;
class MyException
{
    public static void Main()
    {
        int x = 0;
        int div = 0;
        try
        {
            div = 100 / x;
            Console.WriteLine("此行未执行");
        }
        catch (DivideByZeroException de)
        {
            Console.WriteLine("DivideByZeroException");
        }
        catch (Exception)
        {
            Console.WriteLine("Exception");
        }
        finally
        {
            Console.WriteLine("Finally块");
        }
        Console.WriteLine($"结果为 {div}");
    }
}

捕获所有异常

通过提供没有方括号或参数的catch块,我们可以捕获try块内发生的所有异常。

即使我们可以使用带有Exception类型参数的catch块来捕获try块内发生的所有异常,因为在C#中,所有异常都直接或间接地从Exception类继承。  

using System;  
class MyException
{  
    public static void Main()  
    {  
        int x = 0;  
        int div = 0;  
        try  
        {  
            div = 100 / x;  
            Console.WriteLine("此行未执行");  
        }  
        catch  
        {  
            Console.WriteLine("oException");  
        }  
        Console.WriteLine($"结果为 {div}");  
    }  
}

以下程序使用Exception对象处理所有异常。 

using System;
class MyException
{
    public static void Main()
    {
        int x = 0;
        int div = 0;
        try
        {
            div = 100 / x;
            Console.WriteLine("此行未执行");
        }
        catch (Exception)
        {
            Console.WriteLine("oException");
        }
        Console.WriteLine($"结果为 {div}");
    }
}

引发异常

在C#中,可以以编程方式引发异常。为此,使用了“ throw”关键字。引发异常的一般形式如下。 

throw exception_obj; 

例如,以下语句显式引发ArgumentException。

throw new ArgumentException("Exception");
  
using System;
class MyException
{
    public static void Main()
    {
        try
        {
            throw new DivideByZeroException("Invalid Division");
        }
        catch (DivideByZeroException)
        {
            Console.WriteLine("Exception");
        }
        Console.WriteLine("LAST STATEMENT");
    }  
}

重新抛出异常(throw)

我们在catch块内捕获的异常可以通过使用catch块内的关键字throw来重新抛出更高的上下文。

以下程序显示了如何执行此操作。   

//C#: Exception Handling: Handling all exceptions
using System;
class MyClass
{
    public void Method()
    {
        try
        {
            int x = 0;
            int sum = 100 / x;
        }
        catch (DivideByZeroException)
        {
            throw;
        }
    }
}
class MyException
{
    public static void Main()
    {
        MyClass mc = new MyClass();
        try
        {
            mc.Method();
        }
        catch (Exception)
        {
            Console.WriteLine("此处捕获异常");
        }
        Console.WriteLine("LAST STATEMENT");
    }
}

标准例外

异常有两种类型:由执行程序生成的异常和由公共语言运行时生成的异常。

System.Exception是C#中所有异常的基类。多个异常类从该类继承,包括ApplicationException和SystemException。

这两个类构成了大多数其他运行时异常的基础。直接从System.Exception派生的其他异常包括IOException,WebException等。  

公共语言运行库引发SystemException。ApplicationException由用户程序而不是运行时引发。

SystemException包括ExecutionEngineException,StaclOverFlowException等。

不建议我们捕获SystemException,也不建议在我们的应用程序中抛出SystemException。

  • System.OutOfMemoryException
  • System.NullReferenceException
  • Syste.InvalidCastException
  • Syste.ArrayTypeMismatchException
  • System.IndexOutOfRangeException        
  • System.ArithmeticException
  • System.DevideByZeroException
  • System.OverFlowException 

用户定义的异常

在C#中,可以创建我们自己的异常类。但是Exception必须是C#中所有异常的最终基类。

因此,用户定义的异常类必须从Exception类或其标准派生类之一继承。

using System;
 
//用户自定义的异常
class CustomException : Exception
{
    public CustomException(string str)
    {
        Console.WriteLine("用户定义的异常");
    }
}
 
class MyException
{
    public static void Main()
    {
        try
        {
            throw new CustomException("RAJESH");
        }
        catch (Exception e)
        {
            Console.WriteLine("此处捕获异常" + e.ToString());
        }
        Console.WriteLine("LAST STATEMENT");
    }
}

设计准则

异常应用于传达特殊情况。不要使用它们来传达预期的事件,例如到达文件末尾。

如果在System命名空间中有一个很好的预定义异常,它描述了异常情况——一个对类的用户有意义的——使用该类而不是定义一个新的异常类,并在消息中放入特定的信息。

最后,如果代码捕获到了将要处理的异常,请在重新抛出该异常之前考虑是否应将异常与其他信息一起包装。  

try中的return语句先于finally中的函数执行

代码如下:

static void Main(string[] args)
{
    Console.WriteLine(GetNum());
}
 
public static int GetNum()
{
    int Num=1;
    try
    {
        Console.WriteLine("try");
        return Num;
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        ++Num;
        Console.WriteLine("finally");
    }
}

输出结果如下:

结论

try中的return语句先于finally中的函数执行所以,返回的结果是1, 而不是2。

从运行结果可以看出,return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C#保存与读取DataTable信息到XML格式的方法

    C#保存与读取DataTable信息到XML格式的方法

    这篇文章主要介绍了C#保存与读取DataTable信息到XML格式的方法,实例分析了C#读取DataTable信息到XML格式及读取XML格式数据到DataTable的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • C# SetWindowPos函数实例详解

    C# SetWindowPos函数实例详解

    在C#中,SetWindowPos函数用于设置窗口的位置和大小,这篇文章主要介绍了C# SetWindowPos函数实例详解,本文给大家介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • C#设计模式实现之生成器模式和责任链模式

    C#设计模式实现之生成器模式和责任链模式

    学完设计模式之后,你就感觉它会慢慢地影响到你写代码的思维方式,下面这篇文章主要给大家介绍了关于C#设计模式实现之生成器模式和责任链模式的相关资料,需要的朋友可以参考下
    2021-08-08
  • C#生成DLL文件的方法小结

    C#生成DLL文件的方法小结

    这篇文章主要介绍了C#生成DLL文件的方法小结,需要的朋友可以参考下
    2015-07-07
  • Unity延时执行的多种方法小结

    Unity延时执行的多种方法小结

    本文主要介绍了4种延时执行的方法,主要包括Update计时器,Invoke,协程,DoTween,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C# .NET实现扫描识别图片中的文字

    C# .NET实现扫描识别图片中的文字

    本文以C#及VB.NET代码为例,介绍如何扫描并读取图片中的文字。文中的示例代码介绍详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起学习一下
    2021-12-12
  • 详解C#中的out和ref

    详解C#中的out和ref

    本文主要介绍了out和ref的相关知识。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 深入理解C#委托delegate的使用

    深入理解C#委托delegate的使用

    本文主要介绍了C#委托delegate的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • c#实现输出的字符靠右对齐的示例

    c#实现输出的字符靠右对齐的示例

    下面小编就为大家分享一篇c#实现输出的字符靠右对齐的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C#委托用法详解

    C#委托用法详解

    本文详细讲解了C#中委托的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02

最新评论