C#异常与调试

在 C# 语言中,异常也称为运行时异常,它是在程序运行过程中出现的错误。
对于异常的处理需要程序员积累经验,在可能出现异常的位置加入异常处理语句。

C# Exception:异常类

.NET Framework 类库中的所有异常都派生于 Exception 类,异常包括系统异常和应用异常。

默认所有系统异常派生于 System.SystemException,所有的应用程序异常派生于 System.ApplicationException。

系统异常包括 OutOfMemoryException、IOException、NullReferenceException。

常用的异常类如下图所示。
C#异常与调试_第1张图片

常用的系统异常类如下表所示。

异常类 说明
System.OutOfMemoryException 用 new 分配内存失败
System.StackOverflowException 递归过多、过深
System.NullReferenceException 对象为空
Syetem.IndexOutOfRangeException 数组越界
System.ArithmaticException 算术操作异常的基类
System.DivideByZeroException 除零错误

C# try catch finally:异常处理

在 C# 语言中异常与异常处理语句包括三种形式,即 try catch、try finally、try catch finally。

在上述三种异常处理的形式中所用到关键字其含义如下: • try:用于检查发生的异常,并帮助发送任何可能的异常。
• catch:以控制权更大的方式处理错误,可以有多个 catch 子句。
• finally:无论是否引发了异常,finally 的代码块都将被执行。

1) try catch

在 try 语句中放置可能出现异常的语句,而在 catch 语句中放置异常时处理异常的语句,通常在 catch 语句中输出异常信息或者发送邮件给开发人员等。

下面通过实例来演示 try catch 的应用。

另外,在处理异常时,catch 语句是允许多次使用的,相当于多分支的 if 语句,仅能执行其中一个分支。

【实例 1】在文本框中输入一个整数,并判断其是否大于 100。

//如果在文本框中输入的是一个字符串或者浮点数,就会出现类型转换错误,如下图所示。
//如果使用异常处理的语句来处理数据类型转换,则不会岀现上图中的提示,而是出现 catch 语句中弹出的消息框,实现的代码如下。
public partial class tryCatchForm : Form
{
    public tryCatchForm()
    {
        InitializeComponent();
    }
    //“确认”按钮单击事件
    private void button1_Click(object sender, EventArgs e)
    {
        //获取文本框中的值
        string str = textBox1.Text;
        //将字符串装换为整数
        try
        {
            int num = int.Parse(str);
            MessageBox.Show("您输入的数字是:" + num);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}


//使用异常处理后不会再出现上面所示的异常提示,而是弹出 catch 子句中的消息框。

【实例 2】使用多个 catch 语句对程序做异常处理。

//从控制台输入 5 个数存入整数数组中,首先判断输入的值是否为数值,再判断数组元素是否越界。
class Program
{
    static void Main(string[] args)
    {
        //定义存放5个整数的数组
        int[] a = new int[5];
        try
        {
            for(int i = 0; i < a.Length; i++)
            {
                a[i] = int.Parse(Console.ReadLine());
            }
            for(int i = 0; i < a.Length; i++)
            {
                Console.Write(a[i] + " ");
            }
        }
        catch(FormatException f)
        {
            Console.WriteLine("输入的数字格式不正确!");
        }
        catch(OverflowException o)
        {
            Console.WriteLine("输入的值已经超出 int 类型的最大值!");
        }
        catch(IndexOutOfRangeException r)
        {
            Console.WriteLine("数组越界异常!");
        }
    }
}

//捕获该程序产生的异常类是 FormatException。

//这样,在出现不同的异常时都会有相应的异常类来处理异常,这也是比较推荐的一种编程方法。 

2) try finally

在 try finally 形式中没有单独对出现异常时处理的代码,finally 语句是无论 try 中的语句是否正确执行都会执行的语句。

通常在 finally 中编写的代码是关闭流、关闭数据库连接等操作,以免造成资源的浪费。

下面通过实例来演示 try finally 形式的应用。

【实例 3】验证 finally 语句的使用。

//将实例 1 中的 catch 语句换成 finally 语句
public partial class tryCatchForm : Form
{
    public tryCatchForm()
    {
        InitializeComponent();
    }
    //“确认”按钮单击事件
    private void button1_Click(object sender, EventArgs e)
    {
        //获取文本框中的值
        string str = textBox1.Text;
        //将字符串装换为整数
        try
        {
            int num = int.Parse(str);
            MessageBox.Show("您输入的数字是:" + num);
        }
        finally
        {
            MessageBox.Show("finally 语句");
        }
    }
}

//当文本框中输入的值是一个数字字符串时也会执行 finally 语句中的内容

【实例 4】从文本框中输入当天的天气情况,并将其写入文件中,无论写入是否成功都将文件流关闭。

在实例 4 中使用了 try finally 的形式来处理异常,这样在岀现异常时并不会在程序中给予任何提示。

public partial class TryFinallyForm : Form
{
    public TryFinallyForm()
    {
        InitializeComponent();
    }
    //"确认"按钮的单击事件
    private void button1_Click(object sender, EventArgs e)
    {
        //获取文本框
        string city = txtCity.Text;
        string msg = txtMsg.Text;
        string min = txtMin.Text;
        string max = txtMax.Text;
        //将文本框中的内容组成一个字符串
        string message = city + ":" + msg + ":" + min + "~" + max;
        //定义文件路径
        string path = "D:\\C#_test\\weather.txt";
        FileStream fileStream = null;
        try
        {
            //创建fileSteam类的对象
            fileStream = new FileStream(path, FileMode.OpenOrCreate);
            //将字符串转换成字节数组
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            //向文件中写入字节数组
            fileStream.Write(bytes, 0, bytes.Length);
            //刷新缓冲区
            fileStream.Flush();
            //弹出录入成功的消息框
            MessageBox.Show("天气信息录入成功!");
        }
        finally
        {
            if (fileStream != null)
            {
                //关闭流
                fileStream.Close();
            }
        }
    }
}

3) try catch finally

try catch finally 形式语句是使用最多的一种异常处理语句。

在出现异常时能提供相应的异常处理,并能在 finally 语句中保证资源的回收。

【实例 5】使用 try catch finally 形式完成实例 4 的题目要求。

public partial class TryFinallyForm : Form
{
    public TryFinallyForm()
    {
        InitializeComponent();
    }
    //"确认"按钮的单击事件
    private void button1_Click(object sender, EventArgs e)
    {
        //获取文本框
        string city = txtCity.Text;
        string msg = txtMsg.Text;
        string min = txtMin.Text;
        string max = txtMax.Text;
        //将文本框中的内容组成一个字符串
        string message = city + ":" + msg + ":" + min + "~" + max;
        //定义文件路径
        string path = "D:\\C#_test\\weather.txt";
        FileStream fileStream = null;
        try
        {
            //创建fileSteam类的对象
            fileStream = new FileStream(path, FileMode.OpenOrCreate);
            //将字符串转换成字节数组
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            //向文件中写入字节数组
            fileStream.Write(bytes, 0, bytes.Length);
            //刷新缓冲区
            fileStream.Flush();
            //弹出录入成功的消息框
            MessageBox.Show("天气信息录入成功!");
        }
        catch(Exception ex)
        {
            MessageBox.Show("出现错误!" + ex.Message);
        }
        finally
        {
            if (fileStream != null)
            {
                //关闭流
                fileStream.Close();
            }
        }
    }
}


//效果与实例 4 所示的一样,但是当程序出现错误时会弹出 catch 语句中的提示消息。

C#自定义异常(throw抛出异常)

虽然在 C# 语言中已经提供了很多异常处理类,但在实际编程中还是会遇到未涉及的一些异常处理。

例如想将数据的验证放置到异常处理中,即判断所输入的年龄必须为 18〜45,此时需要自定义异常类来实现。

自定义异常类必须要继承 Exception 类。

声明异常的语句如下。

class 异常类名 :Exception
 {

 }

抛出自己的异常,语句如下

throw( 异常类名 );

【实例】自定义异常类,判断从文本框中输入的年龄值处于 18〜45。

class MyException :Exception
{
    public MyException(string message) : base(message)
    {

    }
}


//在“验证”按钮的单击事件中根据输入的年龄判断是否抛出自定义异常,代码如下。 
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        int age = int.Parse(textBox1.Text);
        if (age < 18 || age > 45)
        {
            throw new MyException("年龄必须在18~45岁之间!");
        }
        else
        {
            MessageBox.Show("输入的年龄正确!");
        }
    }
    catch(MyException myException)
    {
        MessageBox.Show(myException.Message);
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

//若在文本框中输入的年龄不在 18〜45 岁即会抛出自定的异常。

//自定义异常也继承自 Exception 类,因此如果不直接处理 MyException 异常,也可以直接使用 Exception 类来处理该异常。

C# Debug和Trace:输出调试信息

在 C# 语言中允许在程序运行时输出程序的调试信息,类似于使用 Console.WriteLine 的方式向控制台输出信息。

所谓调试信息是程序员在程序运行时需要获取的程序运行的过程,以便程序员更好地解决程序中出现的问题,这种调试也被称为是非中断调试。

输出调试信息的类保存在 System.Diagnostics 命名空间中,通常用 Debug 类或 Trace 类实现调试时输出调试信息,具体的语句如下。

Debug.WriteLine();
 Trace.WriteLine();

其中,Debug.WriteLine() 是在调试模式下使用的;Trace.WriteLine 除了可以在调试模式下使用,还可以用于发布的程序中。

【实例】创建一个字符串类型的数组,在数组中存入从控制台输入的值,并输出每次向数组中存入的值。

class Program
{
    static void Main(string[] args)
    {
        string[] str = new string[5];
        Debug.WriteLine("开始向数组中存值:");
        for(int i = 0; i < str.Length; i++)
        {
            str[i] = Console.ReadLine();
            Debug.WriteLine("存入的第{0}个值为{1}", i, str[i]);
        }
        Debug.WriteLine("向数组中存值结束!");
    }
}

运行该程序,在输岀界面中查看通过 Debug 类输出的信息,界面如下图所示。
C#异常与调试_第2张图片

从输出窗口的内容可以看出,通过 Debug 类所打印的内容全部显示在该窗口中。

使用 Trace 类也能完成同样的效果,只需将上述代码中的 Debug 类换成 Trace 类即可。

提示:Trace 类的 WriteLine 方法中的参数不支持上述代码中 Debug 类的 WriteLine 方法的参数形式,只能传递字符串。
需要注意的是当程序在 Debug 状态下执行时使用 Debug 类打印的信息才会在输出窗口中显示,在 Release 状态下执行时只有 Trace 类输出的内容才会显示在输出窗口中。

C#程序调试:VS2015调试程序详解

C#程序调试:VS2015调试程序详解

你可能感兴趣的:(C#)