处理异常和错误>
if语句能检查错误,但必须在运行时。try/catch语句能在编译时检查异常。
处理异常和错误>finally块的用途
当打开文件,操作发生错误,虽然捕捉到异常,但资源没被释放。所以finally块可用来释放资源或其它。
代码
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.IO;
namespace
FinallyDemo
{
class
Program
{
static
void
Main(
string
[] args)
{
const
string
filePath
=
@"
C:\FinallyDemo.txt
"
;
FileStream fs
=
null
;
try
{
Console.WriteLine(
"
开始执行文件的比较操作
"
);
fs
=
new
FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite);
byte
[] bytes
=
Encoding.Default.GetBytes(
"
这是一个字符串,将插入到文本文件
"
);
//
向流中写入指定的字节数组
fs.Write(bytes,
0
,bytes.Length);
//
将缓冲区的内容存储到媒介并清除缓冲区。
fs.Flush();
//
将流指针移到开头。
fs.Seek(
0
, SeekOrigin.Begin);
byte
[] bytes2
=
new
byte
[bytes.Length];
//
从
fs.Read(bytes2,
0
, bytes.Length);
string
str
=
Encoding.Default.GetString(bytes2);
Console.WriteLine(
"
从文件中读出的字符串为
"
+
Environment.NewLine
+
str);
}
catch
(IOException ex)
{
Console.WriteLine(
"
发生了文件处理的错误!
"
+
ex.Message);
}
finally
{
Console.WriteLine(
"
不论是否发生异常,都会执行finally到这里
"
);
if
(fs
!=
null
)
{
fs.Close();
}
Console.ReadLine();
}
}
}
}
处理异常和错误>预定义异常的类
描述:一个总BOSS异常类,引领两个帮派,一个是CLR自己定义好的异常类,另一个便是用户自定义的异常类。异常类嘛,总有些属性,这些属性提供了异常代码的位置,异常的描述信息啊等等。
所有异常类的基类是System.Exception
·SystemException派生的预定义CLR异常类
·ApplicationException派生的用户自定义的应用程序异常类
你可以查看下System.Exception的属性列表。
一个例子:RunMethod调用Method2,Method2调用Method1。Method1抛出一个异常,Method2捕获异常,并将Method1的异常传递给RunMethod, RunMethod调用Exception类的属性,显示异常信息。
显示异常信息
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.IO;
using
System.Collections;
namespace
ExceptionInfos
{
class
Program
{
static
void
Main(
string
[] args)
{
Console.WriteLine(
"
显示额外的信息的结果为:
"
);
Console.WriteLine();
RunMethod(
true
);
Console.WriteLine(
"
不显示额外的信息的结果为:
"
);
Console.WriteLine();
RunMethod(
false
);
Console.ReadLine();
}
///
<summary>
///
显示当前异常和前一个异常的Exception属性信息。
///
</summary>
///
<param name="displayDetails"></param>
static
void
RunMethod(
bool
displayDetails)
{
try
{
Method2();
}
catch
(Exception ex)
{
Console.WriteLine(
"
当前的异常Message属性值为:{0}
"
, ex.Message);
Console.WriteLine(
"
内部异常的Message属性值为:{0}
"
, ex.InnerException.Message);
Console.WriteLine(
"
当前异常的Source属性值为:{0}
"
, ex.Source);
Console.WriteLine(
"
内部异常的Source属性值为:{0}
"
, ex.InnerException.Source);
Console.WriteLine(
"
当前异常StackTrace属性值为:{0}
"
, ex.StackTrace);
Console.WriteLine(
"
内部异常的StackTrace属性值为:{0}
"
, ex.InnerException.StackTrace);
Console.WriteLine(
"
当前异常TargetSite属性值为:{0}
"
, ex.TargetSite);
Console.WriteLine(
"
内部异常的TargetSite属性值为:{0}
"
, ex.InnerException.TargetSite);
Console.WriteLine(
"
当前异常HelpLink属性值为:{0}
"
, ex.HelpLink);
Console.WriteLine(
"
内部异常的HelpLink属性值为:{0}
"
, ex.InnerException.HelpLink);
if
(displayDetails)
{
if
(ex.InnerException.Data
!=
null
)
{
Console.WriteLine(
"
额外的异常信息是:
"
);
foreach
(DictionaryEntry de
in
ex.InnerException.Data)
{
Console.WriteLine(
"
键是:{0},值为{1}
"
, de.Key, de.Value);
}
}
}
}
}
///
<summary>
///
为Exception对象设置值,并直接抛出异常。
///
</summary>
static
void
Method1()
{
Exception ex
=
new
Exception(
"
这是原始异常消息
"
);
string
s
=
"
来自Method1的信息
"
;
int
i
=
100
;
DateTime dt
=
DateTime.Now;
ex.Data.Add(
"
方法信息
"
, s);
ex.Data[
"
整数值
"
]
=
i;
ex.Data[
"
时间值
"
]
=
dt;
throw
ex;
}
///
<summary>
///
为内部异常的Data属性添加更多的信息。
///
</summary>
static
void
Method2()
{
try
{
Method1();
}
catch
(Exception ex)
{
Exception e
=
new
Exception(
"
这是来自Method2的异常信息
"
, ex);
e.InnerException.Data[
"
附件信息
"
]
=
"
来自Method2的信息
"
;
e.InnerException.Data.Add(
"
更多信息
"
,
"
来自Method2的更多信息
"
);
throw
e;
}
}
}
}
处理异常和错误>处理和传递异常
方法A,抛出一个异常A1,方法B,调用A,并且也跑出一个异常B1.如果希望在抛出B1的同时,也传递方法A抛出的异常A1,那么,需要将A1作为一个异常参数传递给B1,这样,跑出B1是,也抛出了A1.
传递异常
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
InnerException
{
class
Program
{
static
void
Main(
string
[] args)
{
try
{
A2();
}
catch
(Exception ex)
{
Console.WriteLine(
"
捕获的异常消息:{0}
"
, ex.Message);
Console.WriteLine(
"
捕获的异常所传递的异常的消息:{0}
"
, ex.InnerException.Message);
Console.ReadLine();
}
}
//
A1直接抛出一个异常
static
void
A1()
{
Exception ex
=
new
Exception(
"
这是来自A1的异常消息
"
);
throw
ex;
}
//
A2调用A1,并将A1抛出的异常保存到InnerException中。
static
void
A2()
{
try
{
A1();
}
catch
(Exception e)
{
Exception ex
=
new
Exception(
"
这是来自A2的异常消息
"
,e);
throw
ex;
}
}
}
}
处理异常和错误>从异常中恢复
正在对两个文件同时执行写操作,对第一个文件的写操作已经完成,执行到对第二个文件的写操作时,抛出了异常。假设程序要求两个文件必须全部写入成功,只要有一个文件的写入失败,就应该回滚对第一个文件的写入。
从异常中恢复
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.IO;
namespace
RollbackException
{
class
Program
{
static
void
Main(
string
[] args)
{
try
{
WriteFile();
}
catch
(Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
///
<summary>
///
异常恢复的示例,假定有两个文件,只要有一个写入失败,就全部回滚。
///
</summary>
static
void
WriteFile()
{
const
string
filePath1
=
@"
C:\RoolbackException1.txt
"
;
const
string
filePath2
=
@"
C:\RoolbackException2.txt
"
;
FileStream fs
=
null
;
FileStream fs1
=
null
;
long
fsPosition
=
0
;
long
fs1Position
=
0
;
try
{
string
str
=
"
这是需要被写入到两个文件中的字符串
"
;
byte
[] bytes
=
Encoding.Default.GetBytes(str.ToCharArray());
fs
=
new
FileStream(filePath1, FileMode.OpenOrCreate, FileAccess.ReadWrite);
//
先将流位置移到文件尾部
fs.Seek(
0
, SeekOrigin.End);
//
获取Position,以用于恢复
fsPosition
=
fs.Position;
//
写入指定的字节数组
fs.Write(bytes,
0
, bytes.Length);
//
写入磁盘清除缓冲区
fs.Flush();
fs1
=
new
FileStream(filePath2, FileMode.CreateNew, FileAccess.ReadWrite);
fs1.Seek(
0
, SeekOrigin.End);
fs1Position
=
fs1.Position;
fs1.Write(bytes,
0
, bytes.Length);
fs1.Flush();
}
//
catch后面并没有加任何表达式,这是可行的,这表示获取所有与CLS兼容或不兼容的异常。
//
一旦发生错误,则将文件恢复到写入前的状态。
catch
{
if
(fs
!=
null
)
{
fs.Position
=
fsPosition;
fs.SetLength(fsPosition);
}
if
(fs1
!=
null
)
{
fs1.Position
=
fs1Position;
fs1.SetLength(fs1Position);
}
throw
;
}
//
执行文件关闭操作。不管有没有引发异常。
finally
{
if
(fs
!=
null
)
{
fs.Close();
}
if
(fs1
!=
null
)
{
fs1.Close();
}
}
}
}
}
处理异常和错误>设计自己的异常
上面“从异常中恢复”,是简单地将系统异常抛出,现在设计抛出一个自定义的WriteFailedException类型的异常。
Program.cs
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
CustomException
{
class
Program
{
static
void
Main(
string
[] args)
{
try
{
WriteFile();
}
catch
(WriteFailedException ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
static
void
WriteFile()
{
throw
new
WriteFailedException();
}
}
}
WriteFailedException.cs
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
CustomException
{
///
<summary>
///
自定义异常类的示例
///
</summary>
public
class
WriteFailedException:ApplicationException
{
public
WriteFailedException()
:
base
(
"
对两个文件的操作产生了一个异常
"
)
{
}
public
WriteFailedException(
string
Message)
:
base
(Message)
{ }
public
WriteFailedException(
string
Message, Exception inner)
:
base
(Message, inner)
{ }
}
}