错误、Bug与异常
bug:
用户错误
异常
.NET基础类库定义了诸如FormatException,IndexOutOfRangeException,FileNotFoundException,ArgumentOutOfRangeException,…等众多异常。
1..NET异常
.NET平台提供了一种标准的技术来发送和捕获运行时错误,这就是结构化异常处理。
2..NET异常处理四要素
一个表示异常详细信息的类类型
一个向调用者抛出异常类实例的成员
调用者一段调用异常成员的代码块
调用者一段处理或捕获异常的代码块
3.异常基类System.Exception
基础类库学习:System.Exception
class Car
{
public void Accelerate(int delta)
{
if(carIsDead)
{
Console.WriteLine("{0} is out of order ...", PetName);
}
else
{
CurrentSpeed += delta;
if(CurrentSpeed >= MaxSpeed)
{
carIsDead = true;
CurrentSpeed = 0;
Exception ex = new Exception(string.Format("{0} has overheated!", PetName));
ex.HelpLink = "http://www.CarsRUs.com";
ex.Data.Add("TimeStamp", string.Format("The car exploded at {0}", DataTime.Now));
ex.Data.Add("Cause", "You have a lead foot.");
// 引发异常
throw ex;
}
else
{
Console.WriteLine("=> CurrentSpeed = {0}", CurrentSpeed);
}
}
}
}
class MyApp
{
static void Main()
{
Console.WriteLine("******Simple Exception Example********");
Car myCar = new Car("Zippy", 20);
try
{
for(int i = 0; i < 10; i++)
{
myCar.Accelerate(10);
}
}
catch(Exception e)
{
Console.WriteLine("\n*** Error! ***");
Console.WriteLine("Method:{0}", e.TargetSite);
Console.WriteLine("Message:{0}", e.Message);
Console.WriteLine("Source:{0}", e.Source);
foreach(DictionaryEntry de in e.Data)
{
Console.WriteLine("-> {0}:{1}", de.Key, de.Value);
}
}
Console.WriteLine("\n*** Out of exception logic ***");
Console.ReadLine();
}
}
4.系统级异常
由.NET基础设施引发的异常,称为系统异常。
系统异常直接派生自名为:System.SystemException的基类。
5.应用程序级异常
最佳实践是,对自定义异常,派生自 System.ApplicationException.
public class CarIsDeadException : ApplicationException
{
private string messageDetails = String.Empty;
public DateTime ErrorTimeStamp{get; set;}
public string CauseOfError{get; set;}
public CarIsDeadException(){}
public CarIsDeadException(string message, string cause, DateTime time)
{
messageDetails = message;
CauseOfError = cause;
ErrorTimeStamp = time;
}
public override string Message
{
get
{
return string.Format("Car Error Message:{0}", messageDetails);
}
}
}
class Car
{
public void Acceleration(int delta)
{
...
CarIsDeadException ex = new CarIsDeadException(string.Format("{0} has overheated!", PetName), "You have a lead foot", DateTime.Now);
ex.HelpLink = "http:://www.CarsRUs.com";
throw ex;
}
}
class MyApp
{
try
{
}
catch(CarIsDeadException e)
{
...
}
}
6.自定义异常的最佳实践
继承自Exception/ApplicationException
有[System.Serializable]特性标记
定义一个默认的构造函数
定义一个设定继承的Message属性的构造函数
定义一个处理 内部异常 的构造函数
定义一个处理类型序列化的构造函数
[Serializable]
public class CarIsDeadException : ApplicationException
{
public CarIsDeadException(){}
public CarIsDeadException(string message)
: base(message){}
public CarIsDeadException(string message, System.Exception inner)
: base(message, inner){}
protected CarIsDeadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
: base(info, context){}
}
7.处理多个异常
class Car
{
public void Accelerate(int delta)
{
if(delta < 0)
{
throw new ArgumentOutOfRangeException("delta", "Speed must be greater than zero!");
}
...
throw new CarIsDeadException(...);
}
}
class MyApp
{
public static void Main()
{
try
{
myCar.Accelerate(-10);
}
catch(CarIsDeadException e)
{
Console.WriteLine(e.Message);
}
catch(ArgumentOutOfRangeException e)
{
...
}
}
}
8.通用catch语句
static void Main()
{
try
{
...
}
catch
{
// try中发生了任何异常都将转入这里
...
}
}
9.在catch中将异常传递
static void Main()
{
try
{
//
}
catch(CarIsDeadException e)
{
...
// 将异常再次抛出
throw;
}
}
10.在catch块中处理时,若操作可能引发异常。
需要在catch块内部使用try/catch处理。
处理一个异常时遇到另一个异常,最好的习惯是将这个新异常对象标识为与第一个异常类型相同的新对象中的“内部错误”。
static void Main()
{
try
{}
catch(CarIsDeadException e)
{
try
{
FileStream fs = File.Open(@"C:\carErrors.txt", FileMode.Open);
}
catch(Exception e2)
{
throw new CarIsDeadException(e.Message, e2);
}
}
}
11.一个try/catch块后面可能接着会定义一个finally块。finally是为了保证不管是否有任何类型的异常,一组代码语句始终能被执行。
static void Main()
{
try
{}
catch(...)
{}
finally
{
myCar.CrankTunes(false);
}
}
12.未处理异常
如果没有成功处理由.NET基础类库方法引发的异常,Visual Studio调试工具将在调用该出错方法的语句处中断。