C#中级教程(1)——解锁 C# 编程的调试与错误处理秘籍

一、认识错误:编程路上的 “绊脚石”

        在 C# 编程中,错误大致可分为两类:语法错误语义错误(逻辑错误)语法错误就像是写作文时的错别字和病句,编译器一眼就能识别出来,比如变量名拼写错误、符号使用不当等,这类错误会导致程序无法正常编译。而语义错误则像是作文的内容逻辑不通顺,代码虽然能正常编译通过,但运行结果却和预期大相径庭,这往往是因为程序的逻辑在某些方面存在瑕疵。

// 错误示例:变量声明时未指定类型
undeclaredVariable = 10; 
// 语义错误示例:判断逻辑错误,原本想判断是否大于5,却写成了小于
int num = 7;
if (num < 5) 
{Console.WriteLine("数字大于5");
}

二、调试技巧:寻找错误的 “放大镜”

(一)正常模式下的调试 “小妙招”

        在正常模式下,借助输出语句来查看变量的值是一种简单有效的调试方法。在使用 Visual Studio(VS)进行 C# 开发时,Console.WriteConsole.WriteLine是我们的得力助手。例如,在一个计算两个数之和的程序中:

int num1 = 5;
int num2 = 10;
int sum = num1 + num2;
Console.WriteLine("num1的值为:" + num1);
Console.WriteLine("num2的值为:" + num2);
Console.WriteLine("两数之和sum的值为:" + sum);

        通过这些输出语句,我们可以清晰地看到每个变量在程序执行过程中的具体值,以此判断程序的运行是否符合预期。如果sum的值不是 15,那就说明代码中可能存在问题,需要进一步排查。

        在 Unity 开发环境中,Debug.LogDebug.LogErrorDebug.LogWarn则发挥着类似的作用。假设我们正在开发一款游戏,角色的移动速度出现了异常,我们可以在相关代码中添加Debug.Log语句:

public class PlayerMovement : MonoBehaviour
{public float speed = 5f;void Update(){Debug.Log("当前角色的移动速度为:" + speed);// 角色移动相关代码}
}

        这样,在 Unity 的 Console 窗口中,我们就能实时查看角色移动速度的变化情况,从而找出速度异常的原因。


(二)中断模式:深入代码内部的 “显微镜”

1.断点:程序的 “暂停按钮”
        断点是进入中断模式的关键。在 VS 中,设置断点的方法多种多样。你可以右键单击代码行,选择 “breakpoint” -> “insert breakpoint”;也可以将光标定位到代码行,通过菜单上的 “Debug” -> “Toggle Breakpoint” 来设置;更为便捷的是,直接按下 F9 键就能快速设置或取消断点;另外,在需要添加断点的行首位置直接单击,同样可以实现断点的添加与取消

        例如,在下面这段代码中:

int result = 0;
for (int i = 1; i <= 10; i++)
{result += i;
}
Console.WriteLine("1到10的累加和为:" + result);

        我们在result += i;这一行设置断点,当程序运行到这一行时,就会自动暂停,进入中断模式。


2.调试窗口:代码状态的 “监控中心”
        进入中断模式后,VS 提供了多个实用的调试窗口,帮助我们深入了解程序的运行状态。
  • 断点窗口:通过 “调试 - 窗口 - 断点” 打开,这里展示了当前项目中所有的断点信息。我们可以在这个窗口中快速定位断点位置,还能方便地删除不再需要的断点。

  • 变量查看窗口:把鼠标指向源代码中的变量名,就能通过工具提示查看变量的信息。此外,在中断模式下的左下角,有 “错误列表”“局部变量”“监视” 三个选项卡。“错误列表” 展示了程序运行中发生的所有错误;“局部变量” 显示当前运行环境中所有局部变量的值;“监视” 则用于跟踪某个特定变量的值的变化。不仅如此,在这些窗口中,我们还能直接修改变量的值,这对于调试复杂的逻辑错误非常有帮助。
  • 调用堆栈和即时窗口:在中断模式的右下角,“调用堆栈” 窗口能让我们清晰地看到当前代码执行到哪一行,以及是被什么语句调用的,这对于理清程序的执行流程至关重要。“即时窗口” 则像是一个小型的代码执行控制台,我们可以在这里输入命令,查看变量的值、修改变量的值,还能输入表达式查看计算结果。例如,在即时窗口中输入result,就能查看当前result变量的值;输入result = 100,可以修改result的值。


3.单步执行:代码执行的 “慢动作”


        单步执行是调试过程中的重要操作,它分为 “逐过程” 和 “逐语句” 两种方式。两者都是逐行执行代码,但 “逐过程” 在遇到函数时,不会进入函数内部,而是把函数当成一条语句直接执行“逐语句” 则会深入函数内部,逐行执行函数中的代码。例如,在下面的代码中:

int num1 = 3;
int num2 = 5;
int sum = AddNumbers(num1, num2);
Console.WriteLine("两数之和为:" + sum);static int AddNumbers(int a, int b)
{return a + b;
}

        如果使用 “逐过程” 执行,当执行到int sum = AddNumbers(num1, num2);时,会直接执行完AddNumbers函数并返回结果;而使用 “逐语句” 执行,则会进入AddNumbers函数内部,逐行执行return a + b;这一行代码。


三、错误处理:程序的 “保护盾”

(一)异常:运行时的 “潜伏危机”

        异常是程序在运行期间产生的错误。例如,当我们访问数组中不存在的元素时,就会引发异常。看下面这个例子:

int[] numbers = { 1, 2, 3 };
try
{int value = numbers[3];
}
catch (IndexOutOfRangeException e)
{Console.WriteLine("发生数组下标越界异常:" + e.Message);
}

        在这个例子中,数组numbers的有效下标范围是 0 到 2,当尝试访问numbers[3]时,就会抛出IndexOutOfRangeException异常。如果不处理这个异常,程序就会终止,后续的代码将无法执行。


(二)异常处理:构建程序的 “防护网”

        C# 中处理异常的语法结构主要由trycatchfinally三个关键字组成。

  • try 块:包含可能会出现异常的代码。例如,在读取用户输入并转换为整数的操作中,可能会因为用户输入非数字字符而引发异常,这部分代码就可以放在try块中:
try
{Console.Write("请输入一个整数:");int number = int.Parse(Console.ReadLine());Console.WriteLine("你输入的整数是:" + number);
}
  • catch 块:用于捕捉并处理异常。当try块中的代码发生异常时,如果异常的类型和catch块中指定的类型匹配,就会执行该catch块中的代码catch块可以有多个,用于处理不同类型的异常。例如:
catch (FormatException e)
{Console.WriteLine("输入的内容格式不正确,请输入一个有效的整数。异常信息:" + e.Message);
}
catch (OverflowException e)
{Console.WriteLine("输入的数字超出了范围。异常信息:" + e.Message);
}

        如果catch块中不指定异常类型,即catch()那么它将捕捉所有类型的异常,但这种方式在实际开发中要谨慎使用,因为它可能会掩盖一些具体的异常信息,不利于问题的排查。

  • finally 块:无论try块中是否发生异常,finally块中的代码都会执行。这在一些需要释放资源的场景中非常有用,比如关闭文件流、数据库连接等。例如:
finally
{Console.WriteLine("这是finally块,无论是否发生异常,我都会被执行。");
}

(三)实际案例:用户输入处理

        接下来,我们通过一个完整的案例来展示异常处理的实际应用。要求用户输入两个数字,计算它们的商,并处理可能出现的异常,如用户输入非数字字符、除数为零等情况。

while (true)
{try{Console.Write("请输入第一个数字:");double num1 = double.Parse(Console.ReadLine());Console.Write("请输入第二个数字:");double num2 = double.Parse(Console.ReadLine());if (num2 == 0){throw new DivideByZeroException("除数不能为零");}double result = num1 / num2;Console.WriteLine("两数相除的结果是:" + result);break;}catch (FormatException e){Console.WriteLine("输入的内容格式不正确,请输入有效的数字。异常信息:" + e.Message);}catch (DivideByZeroException e){Console.WriteLine(e.Message);}catch (Exception e){Console.WriteLine("发生了其他异常:" + e.Message);}
}

        在这个案例中,使用while (true)循环确保用户在输入有误时能够重新输入。try块中包含了获取用户输入、转换为数字以及计算除法的代码。通过多个catch块分别处理不同类型的异常,最后使用finally块来执行一些无论是否发生异常都需要执行的操作(在这个案例中没有添加特定的finally代码,但在实际应用中可以根据需求添加)。


四、总结

        调试和错误处理是 C# 编程中至关重要的技能,它们就像编程道路上的 “护航员”,帮助我们及时发现并解决代码中的问题,确保程序的稳定运行。通过合理运用各种调试技巧和正确处理异常,我们能够编写出更加健壮、可靠的程序。希望大家在今后的编程实践中,不断积累经验,熟练掌握这些技能,让编程之路更加顺畅。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22875.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QML Button 部件的使用

按钮也是程序开发中最经常用到的部件&#xff0c;当然其也是比较简单&#xff0c;只需要懂得最基本的操作即可&#xff1b; Button {id: btnwidth: 100height: 50 } 生成一个最基本的按钮 text 属性可以设置按钮文本&#xff1b; flat 属性设置为true时&#xff0c;只有鼠标…

Starlink卫星动力学系统仿真建模第七讲-卫星姿轨控系统(Attitude and Orbit Control System, AOCS)设计规范

以下是一份卫星姿轨控系统&#xff08;Attitude and Orbit Control System, AOCS&#xff09;设计规范的框架和核心内容示例&#xff0c;供参考&#xff1a; 卫星姿轨控系统&#xff08;AOCS&#xff09;设计规范 1. 总则 1.1 目的 本规范旨在规定卫星姿轨控系统的设计要求、…

DINOv2 + yolov8 + opencv 检测卡车的可拉拽雨覆是否完全覆盖

最近是接了一个需求咨询图像处理类的&#xff0c;甲方要在卡车过磅的地方装一个摄像头用检测卡车的车斗雨覆是否完全&#xff0c; 让我大致理了下需求并对技术核心做下预研究 开发一套图像处理软件&#xff0c;能够实时监控经过的卡车并判断其车斗的雨覆状态。 系统需具备以下…

基础dp——动态规划

目录 一、什么是动态规划&#xff1f; 二、动态规划的使用步骤 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 三、试题讲解 1.最小花费爬楼梯 2.下降路径最小和 3.解码方法 一、什么是动态规划&#xff1f; 动态规划&#xff08;Dynamic Programming&…

Java+Vue+SpringBoot+数据可视化的小吃摊位管理平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在繁华的美食街区&#xff0c;美食摊位星罗棋布&#xff0c;每天都上演着热闹非凡的烟火…

链表-基础训练(二)链表 day14

两两交换链表中的节点 题目示意&#xff1a; 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 原先我的思路是图像上的思路&#xff0c;但是我感觉还是很复杂…

进程概念、PCB及进程查看

文章目录 一.进程的概念进程控制块&#xff08;PCB&#xff09; 二.进程查看通过指令查看进程通过proc目录查看进程的cwd和exe获取进程pid和ppid通过fork()创建子进程 一.进程的概念 进程是一个运行起来的程序&#xff0c;而程序是存放在磁盘的&#xff0c;cpu要想执行程序的指…

极客大学 java 进阶训练营怎么样,图文详解

Spring 思维导图 Spring 源码学习笔记 有关微服务的面试题&#xff1a; Dubbo中zookeeper做注册中心&#xff0c;如果注册中心集群都挂掉&#xff0c;发布者和订阅者之间还能通信么&#xff1f;微服务学习笔记 有关分布式的面试题&#xff1a; 消息幂等:如何保证消息不被重复…

如何手动设置u-boot的以太网的IP地址、子网掩码、网关信息、TFTP的服务器地址,并进行测试

设置IP地址 运行下面这条命令设置u-boot的以太网的IP地址&#xff1a; setenv ipaddr 192.168.5.9设置子网掩码 运行下面这条命令设置u-boot的以太网的子网掩码&#xff1a; setenv netmask 255.255.255.0设置网关信息 运行下面这条命令设置u-boot的网关信息&#xff1a; …

使用大语言模型对接OA系统,实现会议室预定功能

随着人工智能技术的不断进步&#xff0c;越来越多的企业开始借助 AI 助手来提高工作效率&#xff0c;尤其是在日常事务的自动化处理中。比如&#xff0c;在许多公司里&#xff0c;会议室的预定是一个常见且频繁的需求&#xff0c;通常需要员工手动检查空闲时间并做出选择。而通…

单链表:数据结构中的灵活“链条”

目录 &#x1f680;前言&#x1f914;单链表是什么&#xff1f;&#x1f4af;单链表的结构特点&#x1f4af;单链表的用途 ✍️单链表的实现与接口解释&#x1f4af;打印链表&#x1f4af;尾插操作&#x1f4af;头插操作&#x1f4af;头删操作&#x1f4af;尾删操作&#x1f4a…

Redis面试宝典【刷题系列】

文章目录 一、什么是Redis&#xff1f;二、Redis相比Memcached有哪些优势&#xff1f;三、Redis支持的数据类型有哪些&#xff1f;四、Redis的主要消耗的物理资源是什么&#xff1f;五、Redis的全称是什么&#xff1f;六、Redis有哪些数据淘汰策略&#xff1f;七、为什么Redis需…

uni-app集成sqlite

Sqlite SQLite 是一种轻量级的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于各种应用程序中&#xff0c;特别是那些需要嵌入式数据库解决方案的场景。它不需要单独的服务器进程或系统配置&#xff0c;所有数据都存储在一个单一的普通磁盘文件中&am…

pytest-html

首先安装pytest-html库 #执行命令 pytest --htmlreport.html ./pytest-html.pyimport pytest import logging def test_pass():"""用例通过"""assert Truedef test_fail():"""用例失败"""assert Falsedef test_e…

kafka为什么这么快?

前言 Kafka的高效有几个关键点&#xff0c;首先是顺序读写。磁盘的顺序访问速度其实很快&#xff0c;甚至比内存的随机访问还要快。Kafka在设计上利用了这一点&#xff0c;将消息顺序写入日志文件&#xff0c;这样减少了磁盘寻道的时间&#xff0c;提高了吞吐量。与传统数据库的…

从DeepSeek的爆火来看大模型微调技术的发展方向

“深度人工智能”是成都深度智谷科技旗下的人工智能教育机构订阅号&#xff0c;主要分享人工智能的基础知识、技术发展、学习经验等。此外&#xff0c;订阅号还为大家提供了人工智能的培训学习服务和人工智能证书的报考服务&#xff0c;欢迎大家前来咨询&#xff0c;实现自己的…

Dify使用教程(创建应用)

Dify的安装部署我已经写过了&#xff0c;简单的模型配置我也在前面进行了讲解&#xff0c;今天我们主要来讲讲如何使用Dify。 一、创建应用 我们可以通过三种方式在Dify的工作室内创建应用 01 基于应用模板创建&#xff08;新手推荐&#xff09;02 创建一个空白应用03 通过D…

system verilog的流操作符

流操作符&#xff0c;有分为操作对象是一整个数组和单独的数据两种&#xff0c;例如bit [7:0] a[4]和bit [31:0] b&#xff0c;前者操作对象是数组&#xff0c;后者是单独一个较大位宽的数。 流操作符有<<和>>&#xff0c;代表从右向左打包和从左向右打包。 打包的…

项目实战--网页五子棋(匹配模块)(4)

上期我们完成了游戏大厅的前端部分内容&#xff0c;今天我们实现后端部分内容 1. 维护在线用户 在用户登录成功后&#xff0c;我们可以维护好用户的websocket会话&#xff0c;把用户表示为在线状态&#xff0c;方便获取到用户的websocket会话 package org.ting.j20250110_g…

hot100_108. 将有序数组转换为二叉搜索树

hot100_108. 将有序数组转换为二叉搜索树 思路 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#…