【原创】C#中级教程学习笔记001-调试和错误处理
其他路径:
CSDN: https://blog.csdn.net/wodehao0808
微信公众号:程序喵星人
更多资源和视频教程,QQ:1902686547
1. 调试和错误处理
1.1 .正常调试
正常调试,主要是指输出日志,根据打印的信息进行判断错误所在;
1.在visual studio 中,主要通过Console.Write / Console.WriteLine 方法向控制台输出信息;
2.在Unity中,主要通过 Debug.Log("") Debug.LogError("") Debug.LogWarn(""),向unity的Console窗口输出信息;
1.2 中断调试
1.2.1 断点
断点是源代码中自动进入中断模式的一个标记,当遇到断点的时候,程序会进入中断模式。
如何插入断点?
1,右击代码行,选择breakpoint(断点) -> insert breakpoint(插入断点)。
2,光标定位到代码行,选择菜单上的Debug(调试)->Toggle Breakpoint(切换断点)。
3,光标定位到代码行,按下F9键,在此按下F9是取消断点。
4,在需要添加断点的行首位置,直接单击,再次单击取消断点
1.2.2 断点窗口
窗口 Breakpoints
可以通过 (调试-窗口-断点),打开断点窗口,这个窗口显示了当前项目中添加了的所有的断点,我们可以在这里定位断点的位置,也可以去删除断点。
1.2.3 监视变量的内容
在中断模式下查看变量值最简单的方式,就是把鼠标指向源代码中的变量名,此时会出现一个工具提示,显示该变量的信息。
中断模式下的窗口(右下角),有三个选项卡:
错误列表 -程序运行中发生的所有错误的列表。
局部变量 -当前运行环境中所有的局部变量的值。
监视 -监视某个变量的值的变化。
在上面的几个窗口中不但可以观察变量值的变化,还可以直接去修改变量中存储的值
1.2.4 调用堆栈和即时窗口
在中断模式下,可以在右下角看到调用堆栈和即时窗口。
在调用堆栈窗口:我们可以观察到当前代码执行到哪一行了,并且可以看到这个代码的是被什么语句调用的。
即时窗口:我们可以在这里输入一些命令,查看变量的值,修改变量的值,可以输入表达式查看结果。
1.2.5 单步执行代码
在中断模式下我们可以单步执行代码,单步执行带有有两种 逐过程和逐语句,他们两个都是一条语句一条语句的执行,区别在于 逐过程 遇到函数,不会进入函数内部,而把函数当成一条语句去执行。
1.2.6 Example: 断点
1.3 异常处理
有时,我们知道可能会有错误发生,但不能100%的肯定他们不会发生,此时最好能预料到错误的发生,编写足够健壮的代码以处理这些错误,而不必中断程序的执行。
异常:是在运行期间代码中产生的错误。
示例:
int[] myArray = {1,2,3,4};
int myEle = myArray[4]; //数组下标越界
运行到这里的时候,会出现异常,这个异常的定义已经在CLR中定义好了。如果我们不去处理这个异常,那么当异常发生的时候,程序会终止掉,然后异常后面的代码都无法执行。
我们处理异常的语法结构如下(包含了三个关键字 try catch finally)
try
{
...
}
catch( <exceptionType> e )
{
...
}
finally
{
}
其中catch块可以有0或者多个,finally可以有0或者1个。
但是如果没有catch块,必须有finally块,没有finally块,必须有catch块,catch块和finally块可以同时存在。
try块包含了可能出现异常的代码(一条或者多条语句)。
catch块用来捕捉异常,当代码发生异常,那么异常的类型和catch块中的类型一样的时候,就会执行该catch块,如果catch块的参数不写,表示发生任何异常都执行这个catch块。
finally块包含了始终会执行的代码,不管有没有异常产生都会执行。
两个案例:
1, 处理刚刚的下标越界异常。
2,让用户输入两个数字,用户可能会出入非数字类型,处理该异常,如果出现该异常就让用户重新输入,输出这两个数字的和。
1.3.1 Example: 异常案例1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 异常案例1
namespace Lesson_1_2
{
class Program
{
static void Main(string[] args)
{
// example_1: 处理下标越界异常。
try
{
int[] intArray = { 1, 2, 3, 4 };
int myEle = intArray[4];
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("发生了异常:IndexOutOfRangeException = " + e.Message);
Console.WriteLine("您访问数组的时候,下标越界了");
}
finally // 不管有没有发生异常,finally都会执行
{
Console.WriteLine("这里是 finally 里面执行的代码");
}
Console.WriteLine("try..catch结束"); // 异常进行了处理,所以发生异常时可以继续执行后面的代码
try
{
int[] intArray = { 1, 2, 3, 4 };
int myEle = intArray[4];
}
catch (NullReferenceException e) // 捕捉的异常不匹配,所以这个catch不会执行
{
Console.WriteLine("发生了异常:NullReferenceException = " + e.Message);
}
catch // 这个 catch 会捕捉出现的任何异常
{
Console.WriteLine("catch 您访问数组的时候,下标越界了");
}
finally
{
Console.WriteLine("这里是 finally 里面执行的代码");
}
Console.WriteLine("try..catch结束"); // 异常进行了处理,所以发生异常时可以继续执行后面的代码
Console.ReadKey();
}
}
}
1.3.2 Example: 异常案例2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// 异常案例2
namespace Lesson_1_3
{
class Program
{
static void Main(string[] args)
{
// example_2: 让用户输入两个数字,用户可能会出入非数字类型,处理该异常,如果出现该异常就让用户重新输入,输出这两个数字的和。
int iNum1 = 0, iNum2 = 0, iSum = 0;
Console.WriteLine("请输入第一个数字:");
while (true)
{
try
{
iNum1 = Convert.ToInt32(Console.ReadLine()); // try中如果语句发生异常,则不会再执行try中剩下的语句。
break; // 没有发生异常,输入成功,终止循环
}
catch
{
Console.WriteLine("您输入的不是一个整数,请重新输入一个数字:");
}
}
Console.WriteLine("请输入第二个数字:");
while (true)
{
try
{
iNum2 = Convert.ToInt32(Console.ReadLine()); // try中如果语句发生异常,则不会再执行try中剩下的语句。
break; // 没有发生异常,输入成功,终止循环
}
catch
{
Console.WriteLine("您输入的不是一个整数,请重新输入一个数字:");
}
}
iSum = iNum1 + iNum2;
Console.WriteLine("输入的数字之和是 = " + iSum);
Console.ReadKey();
}
}
}