C#编程.异常处理(Exception Handling Statements)
C#语言包含结构化异常处理(Structured Exception Handling,SEH)。
throw
The throw statement is used to signal the occurrence(发生) of an anomalous(异常) situation (exception) during the program execution.
Remarks
The thrown exception is an object whose class is derived from System.Exception, as shown in the following example.
class MyException : System.Exception {}
// ...
throw new MyException();
Usually the throw statement is used with try-catch or try-finally statements. A throw statement can be used in a catch block to re-throw the exception that the catch block caught. In this case, the throw statement does not take an exception operand. For more information and examples, see try-catch (C# Reference) and How to: Explicitly Throw Exceptions.
try-catch
The try-catch statement(语句) consists of a try block fllowed by one or more catch clauses(子句),which specify handles for different exceptions.
Remarks
When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. If the currently executing method(当前方法) does not contain such a catch block, the CLR looks at the method that called the current method(调用当前方法的方法), and so on up the call stack. If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.
The try block contains the guarded code(被保护代码) that may cause the exception. The block is executed until an exception is thrown or it is completed successfully. For example, the following attempt(尝试) to cast a null object(赋值一个null对象) raises(引起) the NullReferenceException exception:
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
Although the catch clause(子句) can be used without arguments to catch any type of exception, this usage is not recommended(不推荐这种用法). In general, you should only catch those exceptions that you know how to recover from(在大多数时候,你应该捕获你知道怎样处理的异常). Therefore, you should always specify an object argument derived from(派生于) System.Exception .For example:
catch (InvalidCastException e)
{
}
It is possible to use more than one specific catch clause in the same try-catch statement. In this case, the order of the catch clauses(catch子句的顺序) is important because the catch clauses are examined in order(按顺序检查). Catch the more specific exceptions before the less specific ones(把一般的错误放在特殊的错误之前). The compiler produces an error if you order your catch blocks so that a later block can never be reached(如若你那样安排你catch子句的顺序,因为后面的catch永远到达不到,所以编译器会产生一个错误).Using catch arguments is one way to filter for the exceptions you want to handle(使用catch参数是一种过滤你要处理的错误的方式).
Exception filters are preferable(最好) to catching and rethrowing (explained below) because filters leave the stack unharmed. If a later handler dumps the stack, you can see where the exception originally came from(你可以看见错误在哪里产生的), rather than just the last place it was rethrown(而不仅仅是在哪里抛出的). A common use of exception filter expressions is logging(一种最经常的用法是在日志上面). You can create a predicate function that always returns false that also outputs to a log(你可以创建一个函数,专门利用返回的错误信息生成日志), you can log exceptions as they go by without having to handle them and rethrow(你可以不马上处理和抛出,可以把异常都存入日志中).
A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement(一个throw语句可以被用在catch块中去抛出被catch块捕捉的的异常). The following example extracts source information from an IOException exception, and then throws the exception to the parent method.
catch (FileNotFoundException e)
{
// FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
// Extract some information from this exception, and then
// throw it to the parent method.
if(e.Source != null)
Console.WriteLine("IOException source: {0}", e.Source);
throw;
}
catch (InvalidCastException e)
{
// Perform some action here, and then throw a new exception.
throw new YourCustomException("Put your error message here.", e);
}
catch (InvalidCastException e)
{
if (e.Data == null)
{
throw;
}
else
{
// Take some action.
}
}
static void Main()
{
int n;
try
{
// Do not initialize this variable here.
n = 123;
}
catch
{
}
// Error: Use of unassigned local variable 'n'.
Console.Write(n);
}
Example1
class TryFinallyTest
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
string s = null; // For demonstration purposes.
try
{
ProcessString(s);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() Exception caught.
* */
Example2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestSEH
{
class Program
{
static string[] eTypes = {"none","simple","index","nested index"};
static void Main(string[] args)
{
foreach (string eType in eTypes)
{
try
{
Console.WriteLine("Main() try block reched.");
Console.WriteLine("ThrowException(\"{0}\") called.", eType);
ThrowException(eType);
Console.WriteLine("Main() try block continues.");
}
catch (System.IndexOutOfRangeException e)
{
Console.WriteLine("Main() System.IndexOutOfRangeException catch" + "black reched.Message:\n\"{0}", e.Message);
}
catch
{
Console.WriteLine("Main() general catch block reached.");
}
finally
{
Console.WriteLine("Main() finally block reched.");
}
Console.WriteLine();
}
Console.ReadKey();
}
static void ThrowException(string exceptionType)
{
Console.WriteLine("ThrowException(\"{0}\") reached.",exceptionType);
switch (exceptionType)
{
case "none" :
Console.WriteLine("Not throwing an exception.");
break;
case "simple" :
Console.WriteLine("Throwing System.Exception.");
throw (new System.Exception());
break;
case "index" :
Console.WriteLine("Throwing System.IndexOutOfRangeException.");
eTypes[4] = "error";
break;
case "nested index" :
try
{
Console.WriteLine("ThrowException(\"nested index\")" + "try black reached.");
Console.WriteLine("ThrowException(\"index\") called.");
ThrowException("index");
}
catch (Exception)
{
Console.WriteLine("ThrowException(\"nested index\") general" + "catch block reached.");
}
finally
{
Console.WriteLine("ThrowException(\"nested index\") finally"+"block reched");
}
break;
}
}