C# 异常
异常是为处理异常的发生而设计的,这些特殊情况会改变程序执行的正常流程。 引发或引发异常。
在执行应用期间,许多事情可能出错。 磁盘可能已满,我们无法保存文件。 当我们的应用尝试连接到站点时,Internet 连接可能会断开。 所有这些都可能导致我们的应用崩溃。 程序员有责任处理可以预期的错误。
try
,catch
和finally
关键字用于处理异常。
cs
Program.
using System;
namespace DivisionByZero
{
class Program
{
static void Main(string[] args)
{
int x = 100;
int y = 0;
int z;
try
{
z = x / y;
}
catch (ArithmeticException e)
{
Console.WriteLine("An exception occurred");
Console.WriteLine(e.Message);
}
}
}
}
在上面的程序中,我们有意将数字除以零。 这会导致错误。
cs
try
{
z = x / y;
}
容易出错的语句放置在try
块中。
cs
catch (ArithmeticException e)
{
Console.WriteLine("An exception occurred");
Console.WriteLine(e.Message);
}
异常类型跟随catch
关键字。 在我们的情况下,我们有一个ArithmeticException
。 由于算术,转换或转换操作中的错误而引发此异常。 发生错误时,将执行catch
关键字之后的语句。 发生异常时,将创建一个异常对象。 从该对象中,我们获得Message
属性并将其打印到控制台。
cs
$ dotnet run
An exception occurred
Attempted to divide by zero.
代码示例的输出。
C# 未捕获的异常
当前上下文中任何未捕获的异常都会传播到更高的上下文,并寻找适当的 catch 块来处理它。 如果找不到任何合适的 catch 块,则.NET 运行时的默认机制将终止整个程序的执行。
cs
Program.
using System;
namespace UcaughtException
{
class Program
{
static void Main(string[] args)
{
int x = 100;
int y = 0;
int z = x / y;
Console.WriteLine(z);
}
}
}
在此程序中,我们除以零。 没有自定义异常处理。
cs
$ dotnet run
Unhandled Exception: System.DivideByZeroException: Division by zero
at UncaughtException.Main () [0x00000]
C# 编译器给出了以上错误消息。
C# IOException
发生 I / O 错误时,将抛出IOException
。 在下面的示例中,我们读取文件的内容。
cs
Program.
using System;
using System.IO;
namespace ReadFile
{
class Program
{
static void Main(string[] args)
{
var fs = new FileStream("langs.txt", FileMode.OpenOrCreate);
try
{
var sr = new StreamReader(fs);
string line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
catch (IOException e)
{
Console.WriteLine("IO Error");
Console.WriteLine(e.Message);
}
finally
{
Console.WriteLine("Inside finally block");
if (fs != null)
{
fs.Close();
}
}
}
}
}
始终执行finally
关键字之后的语句。 它通常用于清理任务,例如关闭文件或清除缓冲区。
cs
} catch (IOException e)
{
Console.WriteLine("IO Error");
Console.WriteLine(e.Message);
}
在这种情况下,我们捕获了特定的IOException
异常。
cs
} finally
{
Console.WriteLine("Inside finally block");
if (fs != null)
{
fs.Close();
}
}
这些行确保关闭文件处理程序。
cs
$ cat langs.txt
C#
Java
Python
Ruby
PHP
JavaScript
这些是langs.txt
文件的内容。
cs
$ dotnet run
C#
Java
Python
Ruby
PHP
JavaScript
Inside finally block
这是程序的输出。
我们使用 cat 命令和程序输出显示 langs 文件的内容。
C# 多个异常
我们经常需要处理多个异常。
cs
Program.
using System;
using System.IO;
namespace MultipleExceptions
{
class Program
{
static void Main(string[] args)
{
int x;
int y;
double z;
try
{
Console.Write("Enter first number: ");
x = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter second number: ");
y = Convert.ToInt32(Console.ReadLine());
z = x / y;
Console.WriteLine("Result: {0:N} / {1:N} = {2:N}", x, y, z);
}
catch (DivideByZeroException e)
{
Console.WriteLine("Cannot divide by zero");
Console.WriteLine(e.Message);
}
catch (FormatException e)
{
Console.WriteLine("Wrong format of number.");
Console.WriteLine(e.Message);
}
}
}
}
在此示例中,我们捕获了各种异常。 请注意,更具体的异常应先于一般的异常。 我们从控制台读取两个数字,并检查零除错误和数字格式错误。
cs
$ dotnet run
Enter first number: we
Wrong format of number.
Input string was not in a correct format.
运行示例,我们得到了这个结果。
C# 自定义异常
定制异常是从System.Exception
类派生的用户定义的异常类。
cs
Program.
using System;
namespace CustomException
{
class BigValueException : Exception
{
public BigValueException(string msg) : base(msg) { }
}
class Program
{
static void Main(string[] args)
{
int x = 340004;
const int LIMIT = 333;
try
{
if (x > LIMIT)
{
throw new BigValueException("Exceeded the maximum value");
}
}
catch (BigValueException e)
{
Console.WriteLine(e.Message);
}
}
}
}
我们假定存在无法处理大量数字的情况。
cs
class BigValueException : Exception
我们有一个BigValueException
类。 该类派生自内置的Exception
类。
cs
const int LIMIT = 333;
大于此常数的数字在我们的程序中被视为"大"。
cs
public BigValueException(string msg) : base(msg) {}
在构造函数内部,我们称为父级的构造函数。 我们将消息传递给父母。
cs
if (x > LIMIT)
{
throw new BigValueException("Exceeded the maximum value");
}
如果该值大于限制,则抛出自定义异常。 我们给异常消息"超出最大值"。
cs
} catch (BigValueException e)
{
Console.WriteLine(e.Message);
}
我们捕获到异常并将其消息打印到控制台。
cs
$ dotnet run
Exceeded the maximum value