处理异常和错误>
if语句能检查错误,但必须在运行时。try/catch语句能在编译时检查异常。
处理异常和错误>finally块的用途
当打开文件,操作发生错误,虽然捕捉到异常,但资源没被释放。所以finally块可用来释放资源或其它。
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.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.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.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类型的异常。
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();
}
}
}
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)
{ }
}
}