C# - 异常处理
本文关键字:异常处理 | 更新日期: 2023-09-12 17:39:50
在这里,您将了解 C# 中使用 try、catch 和 finally 块进行异常处理。
必须处理应用程序中的异常以防止程序崩溃和意外结果,记录异常并继续使用其他功能。C# 提供内置支持,使用 try
、catch
和 finally
块来处理异常。
try { // put the code here that may raise exceptions } catch { // handle exception here } finally { // final cleanup code }
try block:任何可能引发异常的可疑代码都应放在try{ }
块中。在执行过程中,如果发生异常,控件的流将跳转到第一个匹配的catch
块。
catch 块:catch
块是一个异常处理程序块,您可以在其中执行某些操作,例如记录和审核异常。catch
块采用异常类型的参数,您可以使用该参数获取异常的详细信息。
finally 块:无论是否引发异常,都将始终执行finally
块。 通常,应使用finally
块来释放资源,例如,关闭在try
块中打开的任何流或文件对象。
如果输入非数字字符,以下内容可能会引发异常。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter a number: ");
var num = int.Parse(Console.ReadLine());
Console.WriteLine($"Squre of {num} is {num * num}");
}
}
若要处理上述示例中可能的异常,请将代码包装在 try
块中,并在 catch
块中处理异常,如下所示。
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Enter a number: ");
var num = int.parse(Console.ReadLine());
Console.WriteLine($"Squre of {num} is {num * num}");
}
catch
{
Console.Write("Error occurred.");
}
finally
{
Console.Write("Re-try with a different number.");
}
}
}
在上面的示例中,我们将此代码包装在 try
块中。如果在try
块内发生异常,则程序将跳转到catch
块。
在catch
块中,我们显示一条消息来指示用户他的错误,而在finally
块中,我们显示一条关于运行程序后要做什么的消息。
注意:
一个try
块后面必须跟着catch
或finally
或两个块。没有 catch
或 finally
块的try
块将给出编译时错误。
理想情况下,catch
块应包含内置或自定义异常类的参数,以获取错误详细信息。以下内容包括捕获所有类型的异常的 Exception
类型参数。
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Enter a number: ");
var num = int.parse(Console.ReadLine());
Console.WriteLine($"Squre of {num} is {num * num}");
}
catch(Exception ex)
{
Console.Write("Error info:" + ex.Message);
}
finally
{
Console.Write("Re-try with a different number.");
}
}
}
异常过滤器
您可以使用具有不同异常类型参数的多个catch
块。这称为异常筛选器。当您希望以不同的方式处理不同类型的异常时,异常筛选器非常有用。
class Program
{
static void Main(string[] args)
{
Console.Write("Please enter a number to divide 100: ");
try
{
int num = int.Parse(Console.ReadLine());
int result = 100 / num;
Console.WriteLine("100 / {0} = {1}", num, result);
}
catch(DivideByZeroException ex)
{
Console.Write("Cannot divide by zero. Please try again.");
}
catch(InvalidOperationException ex)
{
Console.Write("Invalid operation. Please try again.");
}
catch(FormatException ex)
{
Console.Write("Not a valid format. Please try again.");
}
catch(Exception ex)
{
Console.Write("Error occurred! Please try again.");
}
}
}
在上面的例子中,我们指定了多个具有不同异常类型的catch
块。我们可以根据错误向用户显示适当的消息,因此用户不会再次重复相同的错误。
注意:
不允许使用具有相同异常类型的多个catch
块。具有基本异常类型的catch
块必须是最后一个块。
无效的捕获块
在同一个 try
-catch 语句中不允许使用无参数catch
块和具有 Exception
参数的catch
块,因为它们都执行相同的操作。
try
{
//code that may raise an exception
}
catch //cannot have both catch and catch(Exception ex)
{
Console.WriteLine("Exception occurred");
}
catch(Exception ex) //cannot have both catch and catch(Exception ex)
{
Console.WriteLine("Exception occurred");
}
此外,无参数捕获块catch{ }
或常规捕获块catch(Exception ex){ }
必须是最后一个块。如果在catch{ }
或catch(Exception ex)
块之后有其他catch
块,编译器将给出错误。
try
{
//code that may raise an exception
}
catch
{
// this catch block must be last block
}
catch (NullReferenceException nullEx)
{
Console.WriteLine(nullEx.Message);
}
catch (InvalidCastException inEx)
{
Console.WriteLine(inEx.Message);
}
finally Block
finally
块是可选块,应位于try
或捕获块之后。无论是否发生异常,都将始终执行finally
块。finally
块通常用于清理代码,例如,处置非托管对象。
static void Main(string[] args)
{
FileInfo file = null;
try
{
Console.Write("Enter a file name to write: ");
string fileName = Console.ReadLine();
file = new FileInfo(fileName);
file.AppendText("Hello World!")
}
catch(Exception ex)
{
Console.WriteLine("Error occurred: {0}", ex.Message );
}
finally
{
// clean up file object here;
file = null;
}
}
注意:
不允许多个finally
块。此外,finally
块不能有返回、继续或中断关键字。它不会让控制权离开finally
块。
嵌套尝试捕获
C# 允许嵌套的 try-catch 块。使用嵌套的 try-catch 块时,将在发生异常的try
块之后的第一个匹配catch
块中捕获异常。
static void Main(string[] args)
{
var divider = 0;
try
{
try
{
var result = 100/divider;
}
catch
{
Console.WriteLine("Inner catch");
}
}
catch
{
Console.WriteLine("Outer catch");
}
}
输出:
Inner catch在上面的示例中将执行内部catch
块,因为它是处理所有异常类型的第一个catch
块。
如果没有与引发的异常类型匹配的内部catch
块,则控件将流向外部catch
块,直到找到适当的异常筛选器。请考虑以下示例。
static void Main(string[] args)
{
var divider = 0;
try
{
try
{
var result = 100/divider;
}
catch(NullReferenceException ex)
{
Console.WriteLine("Inner catch");
}
}
catch
{
Console.WriteLine("Outer catch");
}
}
输出:
Outer catch在上面的示例中,将引发类型 DivideByZeroException
的异常。因为内catch
块只处理NullReferenceTypeException
,所以它将由外catch
块处理。