C#OOP之十 异常机制及其处理

异常简介

索引越界、文件I/O出错、堆栈溢出、除零运算问题、数据库无法使用等一个个问题,对于我们来说如何保证系统容错和程序规范,异常机制是不可或缺的重要因素和手段。良好的系统设计必定有良好的异常处理机制来保证程序的健壮性和容错机制。

不可靠的程序含有很多“臭虫”(也叫Bug),含有臭虫的代码我们称之为有”臭味”(BadShell)。软件领域的Bug是无处不在的,所以,不要轻言自己的程序已经完美了。其实,只是你现在还没发现Bug,或者说还没有能力来发现Bug而已,当然,完全没有Bug的程序是不存在的,我们只能尽量去发现。正如软件测试的目的一样:尽可多的去发现错误。

那么,我们回想以前自己做的程序,是否在编程的时候针对一些细节问题没做处理呢?比如:除零问题、文件I/O问题等。错误按照发生机理一般可以分为两类:

一.语法错误

类似于我们语文中的写了一篇文章不加标点符号一样,导致会出现多种读法。在C#程序中,语句的开始结束有强制的规定,不能多或少一些符号,毕竟计算机还是基于逻辑判断的机器。常见的语法错误如下:

1)       语句结束少了分号;

2)       类型匹配错误。

3)       变量书写错误。

4)       空值错误。“空对象或空引用”的问题。

5)       相等值比较。

6)       数组越界。

7)       If else 或switch case 匹配问题。

8)       随便使用析构函数。

二.逻辑错误

1)       语法错误导致语法逻辑错误。

2)       处理逻辑本身的错误。例如:求圆周长:使用公式2*PI*R*R,避免此种错误,就需要一本小学数学书籍做参考了。:)

假如为银行做ATM项目(自动取款机),个人感觉利息的计算精确到小数点后两位就可以了。假如说你省略带的利息位0.005(四舍五入到0.01)计算,10000000次交易就是5000元。对于客户或银行都可能造成莫大的损失。

或者在ATM项目中没有考虑取款额范围的问题,假如有客户一次取款1000000,那么ATM机可能会忙的发热烧掉哦。即使没烧掉,也可能没这么多钱让你取。

从try/catch/finally说起:深入异常机制

深入理解异常机制,需要认真研究try/catch/finally块应用。在C#中针对程序中可能出现的各种异常,主要有如下几种。

1. 一个try块后跟一个或多个catch块。

Try

{

目标代码块

}

catch(异常类名1  异常变量名2)

{

异常处理代码1

}

catch(异常类名2  异常变量名2)

{

异常处理代码2

}

2. 一个try块后跟一个或多个catch块

Try

{

目标代码块

}

catch(异常类名1  异常变量名2)

{

异常处理代码1

}

catch(异常类名2  异常变量名2)

{

异常处理代码2

}

finally

{//无论是否执行,代码都会执行

}

项目1:使用C#异常来实现除法运算

项目背景:排除除零错和其他常规错误。

步骤1:考虑有多少种异常

步骤2:编码、采用多个catch块

usingSystem;

classExceptionDemo

{

static void Main(string[]args)

{

try

{

intnum1,num2,result;

Console.WriteLine("本程序实现除法运算:");

Console.Write("请输入被除数:");

num1=Int32.Parse(Console.ReadLine());

Console.Write("请输入除数:");

num2=Int32.Parse(Console.ReadLine());

result=num1/num2;

Console.WriteLine("{0}/{1}={2}",num1,num2,result);

}/*catch(DivideByZeroExceptiona)                 //e:这是一个DivideByZeroException异常类的对象;

{

Console.WriteLine("-----------------------");

Console.WriteLine("{0}",a);

Console.WriteLine("异常信息:{0}",a.Message);

Console.WriteLine("引发异常的来源:{0}",a.Source);

}catch(OverflowException)//在选中的上下文中所进行的算术运算、类型转换或转换操作导致溢出时引发的异常

{

Console.WriteLine("您输入的数字太大了,已经超过系统允许的范围!");

}*/

catch(FormatException)//当参数格式不符合调用的方法的参数规范时引发的异常。

{

Console.WriteLine("您输入的格式不对");

}

catch(Exception)

{

Console.WriteLine("我的程序没有错误,永远对!!!打肿脸充张洋");

}     //首先catch子类(范围比较小的),然后catch超类(范围比较大的异常类)

finally

{

Console.WriteLine("最后不管有没有问题都执行!!!");

//垃圾回收不好控制:比如说数据库连接;最后需要关闭数据库连接.

//里面还可以写try-catch-finally

}

}

}

步骤3:编译csc ExceptionDemo.cs

步骤4:运行ExceptionDemo

步骤5:观察效果,并思考是否可以进一步改进代码

异常类的层次结构

异常类的层次结构图如下,当然不能在次将所有异常类都一一列举。主要让大家明了系统异常类和自定义异常类。`

常见系统异常类说明如下:

常见系统异常类说明如下:


系统异常类


说    明


IndexOutOfRangeException


数组索引异常


NullReferenceException


空引用异常(对象为null,而直接使用)


DivideByZeroException


除数为0时异常


IOException


文件读写IO操作异常


DataException


数据库访问操作异常


ApplicationException


非致命应用程序引发异常


ArrayTypeMismatchException


数组类型不正确的引发异常


OverflowException


算术运算、类型转换导致的溢出异常


InvalidCastException


无效类型转换引发异常


OutOfMemoryException


没有足够内存继续执行程序引发的异常

了解一个异常类的体系,有必要认真学习System.Exception这个基类,其常用属性如下:


 


名称


说明


Data


获取一个提供用户定义的其他异常信息的键/值对的集合。


HelpLink


获取或设置指向此异常所关联帮助文件的链接。


HResult


获取或设置 HRESULT,它是分配给特定异常的编码数值。


InnerException


获取导致当前异常的 Exception 实例。


Message


获取描述当前异常的消息。


Source


获取或设置导致错误的应用程序或对象的名称。


StackTrace


获取当前异常发生时调用堆栈上的帧的字符串表示形式。


TargetSite


获取引发当前异常的方法。

如何抛出异常

在C#中,有如下两种异常引发方式。

n       主动引发异常:使用throw语句来立即、无条件地引发异常。控制永远不会到达紧跟在throw后面的语句。对程序来说,主动地检查到了错误或者意外事件,因此引发了一个异常来通知用户或者调用代码。

n       系统引发异常:在执行C#语句和表达式的过程中,有时会出现一些例外情况,使某些操作无法正常完成,此时就会引发一个异常。对程序来说,这种异常是被动地发生的。例如,整数除法运算中,如果分母为零,则会引发System.DivideByZeroException,会出现这种异常是因为进行除法之前,程序没有主动地检查除法是否为零。一般地,系统引发的异常都是.Net框架类库中定义的公共异常类所表示的异常。

Throw语句格式:

Throw[异常表达式]

带表达式的throw语句引发一个异常,此异常的值就是通过计算该表达式而产生的值。计算该表达式所得的值是System.Exception或从System.Exception派生的类的对象。如果表达式的计算产生null,则引发System.NullReferenceException。

不带表达式的throw语句只能用在catch块中,此种情况下,该语句重新引发当前正由该catch块处理的那个异常。

由于throw语句无条件地控制到别处,因此永远无法到达throw语句的结束点。

案例:

// Rectangle.cs

// throw示例

using System;

public class Rectangle

{

protected int width;

protected int height;

public int Width

{

get

{

return width;

}

set

{

if (value > 0)

width = value;

else

throw new Exception("Width的值不能为负数。");

}

}

public int Height

{

get

{

return height;

}

set

{

if (value > 0)

height = value;

else

throw newException("Height的值不能为负数。");

}

}

public Rectangle()

{

}

public Rectangle(int cx, int cy)

{

Width = cx;

Height = cy;

}

public static void Main()

{

Rectangle rect = new Rectangle();

rect.Width = -1;

}

}

运行上述程序将会引发异常,因为当给Rectangle类的对象的Width属性赋负值时,将调用throw语句。

自定义异常

有时我们可能会碰到系统异常类无法提供合适异常类型的情况,此时我们就需要自定义异常类。格式:

classMyException:ApplicationException

{

Public MyException():base(“自定义异常处理消息”)

{}

}

为什么可以调用基类的带字符串的构造函数,System.Exception的构造函数格式会看出端倪。

PublicException(string message);

PublicException(string message,Exception innerException);

可以使用throw语句来抛出自定义的异常,代码如下:

//MyException.cs

// 自定义异常类示例

usingSystem;

classMyException : ApplicationException

{

public MyException()

: base("自定义异常信息。")

{

}

}

classTest

{

public static void Main()

{

try

{

throw new MyException();

}

catch (MyException ex)

{

Console.WriteLine(ex.Message);

}

}

}

实践问题:

选择题:

1. 异常处理块可以使用的关键字下面哪一个不正确()

A try                       Bcatch

C finally                   D final

2.下面哪一个不是在程序中发生错误的类型()

A 语法错误                 B运行时错误

C 空值错误                 D 逻辑错误

3.没有任何表达式的throw 语句紧被用在以下哪个块中()

A finally                   B catch

C throw                     D try

4.所有的异常都派生自()类

A System.Exception          B System.ApplicationException

C System.SystemException    D System.DataException

小结:

在本章中,我们主要学习了:

u      异常是什么

u      如何使用异常

u      异常的类型和层次结构

u      开发自己的自定义异常类

英语词汇:

英文            
全文                                        
中文

Exception                           异常

Range                               范围

Null                                空的

Memory                              内存

Try                             尝试

Catch                               捕获

Finally                             最终

Handle                              处理

Throw                               抛出

Average                        平均数

Found                               发现,  找到

IOException                             文件读写等IO操作异常

DataException                   进行数据库访问等操作发生错误时引发的异常

ApplicationException                    发生非致命错误时引发的异常

练习项目:

1.编写一个程序,要求用户输入手机号,手机号必须符合规范。编写一个手机号格式不符合规范的自定义异常继承自Application,如果手机号不符合规范则抛出异常错误。

手机规范为:只能是13位数字,不能是其他任何字符。第一必须是1, 第二位必须是3或5。

时间: 2024-10-08 13:10:59

C#OOP之十 异常机制及其处理的相关文章

Atitit. Java script 多重多重catch语句的实现and Javascript js 异常机制

Atitit. Java script 多重多重catch语句的实现and Javascript js 异常机制 1. 语法错误(ERROR)和运行期错误(Exception) 1 2. 错误类型判断 二种方法: 1 3. 我们常接触到的异常包括: 2 4. ------代码 2 5. 参考 4 1. 语法错误(ERROR)和运行期错误(Exception) Javascript提供了两种特殊的错误处理方式 BOM包含一个onerror事件处理函数,这个window对象与图像对象上都有 同时EC

异常机制

1. 异常机制       异常机制是指当程序出现错误后,程序如何处理.具体来说,异常机制提供了程序退出的安全通道.当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器. 传统的处理异常的办法是,函数返回一个特殊的结果来表示出现异常(通常这个特殊结果是大家约定俗称的),调用该函数的程序负责检查并分析函数返回的结果.这样做有如下的弊端:例如函数返回-1代表出现异常,但是如果函数确实要返回-1这个正确的值时就会出现混淆:可读性降低,将程序代码与处理异常的代码混爹在一起:由调用函数的程序

第六章:异常机制

第六章:异常机制 异常的定义 异常:在程序运行过程中出现的意外事件,导致程序中断执行. 异常处理 try...catch 语法:try{ //可能出现异常的代码}catch(异常类型 异常对象名){ //处理异常的代码:}执行过程:当try中的代码异常发生时抛出一个异常对象,该异常对象与catch中异常类型进行匹配,匹配成功进入catch块,否则不执行catch中代码(相当于异常未被处理).程序只有当异常处理成功后才能继续执行. try...catch...catch 语法:try{ //可能出

C++ Primer笔记2_四种类型转换_异常机制

1.类型转换 命名的强制类型转换: 有static_cast.dynamic_cast.const_cast.reinterpret_cast static_cast: 编译器隐式执行的任何类型转换都可以由static_cast完成 当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换. 可以将void*指针转换为某一类型的指针 可以将基类指针强制转换为派生类指针,但是不安全. 无法将const转化为nonconst,这个只有const_cast才可以办得到 举例:

Java的异常机制

一.什么是异常:非正常的,不同寻常的,不是语法错误. 生活中,医生说你身体某个部位异常,该部位和正常相比,有点不同功能可能受损. 张三开车去上班,正常情况下,顺利到达公司 非正常情况下,车子坏了,走路去公司 异常指的 不是语法错误 ,语法错误编译通不过,不会产生字节码文件,根本不能运行 程序中:代码出现错误,程序就会停止运行. 异常处理是衡量一门语言是否成熟的标准之一.主流的java c++ c# 都有异常处理机制. 异常处理可以让程序有更好的容错性,使代码更健壮. 传统的c语言是没有异常处理的

java 异常机制

浅谈java异常机制 下班闲来无事,看看java基础知识,做一下总结 异常机制:是java提供的一个解决突发事件或者误操作的一种控制流程的一种解决方案 Throwable 所有错误或者异常的超类,包含两个子类Error和Exection 其中Error错误是程序无法处理的,如内存溢出.机器断电等 Exception异常包括运行时异常和编译时异常 运行时异常类均继承RuntimeException,常见的如NullPointerException,ArithmeticException,Index

关于java中异常机制

什么是异常:异常就是程序在运行时出现的不正常情况.对于严重的情况Java通过Error类进行描述,一般不用编写代码处理:对于不严重的情况Java通过Exception描述,一般编写针对性代码对其进行处理. 异常由来:问题也是生活中一个具体的事物,也可以通过Java类的形式进行描述(比如进行运算时被除数不可以为0否则出现ArithmeticException异常,数组越界会出现ArrayIndexOutOfBoundsException等等),并封装成对象.即Java对不正常情况进行描述后的对象体

C++异常机制的实现方式和开销分析 (大图,编译器会为每个函数增加EHDL结构,组成一个单向链表,非常著名的“内存访问违例”出错对话框就是该机制的一种体现)

白杨 http://baiy.cn 在我几年前开始写<C++编码规范与指导>一文时,就已经规划着要加入这样一篇讨论 C++ 异常机制的文章了.没想到时隔几年以后才有机会把这个尾巴补完 :-). 还是那句开场白:“在恰当的场合使用恰当的特性” 对每个称职的 C++ 程序员来说都是一个基本标准.想要做到这点,就必须要了解语言中每个特性的实现方式及其时空开销.异常处理由于涉及大量底层内容,向来是 C++ 各种高级机制中较难理解和透彻掌握的部分.本文将在尽量少引入底层细节的前提下,讨论 C++ 中这一

C++ 异常机制分析(C++标准库定义了12种异常,很多大公司的C++编码规范也是明确禁止使用异常的,如google、Qt)

阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexcept操作符 异常处理的性能分析 正文 回到顶部 C++异常机制概述 异常处理是C++的一项语言机制,用于在程序中处理异常事件.异常事件在C++中表示为异常对象.异常事件发生时,程序使用throw关键字抛出异常表达式,抛出点称为异常出现点,由操作系统为程序设置当前异常对象,然后执行程序的当前异常处理代码块,在包含了异常出现点的