在本文中,我们展示了如何在C#中处理异常。
异常表示应用程序执行期间发生的错误。
在我们的应用程序执行期间,许多事情可能会出错。磁盘可能已满,我们无法保存文件。当我们的应用程序尝试连接到某个站点时,Internet连接可能会中断。这些错误可能会导致包括应用程序崩溃在内的问题。程序员有责任处理可以预见的错误。
try
、catch
和finally
关键字用于处理异常。
Exception
是所有异常的基类。错误由抛出的异常报告。抛出异常后,由应用程序或默认异常处理程序处理。异常包含有关错误的信息。
在应用程序开发期间和开发完成后会抛出不同类型的异常。开发人员会收到包含大量技术细节的异常,而用户只会收到简短、基本的信息性消息。
C#捕获异常
catch
关键字用于捕获抛出的异常。
int x = 100; int y = 0; int z; try { z = x / y; } catch (ArithmeticException e) { Console.WriteLine("An exception occurred"); Console.WriteLine(e.Message); }
在上面的程序中,我们有意将一个数字除以零。这会导致错误。请注意,这是一个演示异常如何工作的学术示例。实际上,被错误除法是一个程序错误,通过确保分母不为零来解决。
try { z = x / y; }
容易出错的语句放在try
块中。
catch (ArithmeticException e) { Console.WriteLine("An exception occurred"); Console.WriteLine(e.Message); }
异常类型跟在catch
关键字之后。在我们的例子中,我们有一个ArithmeticException
。此异常会因算术、转换或转换操作中的错误而抛出。catch
关键字后面的语句在发生错误时执行。当异常发生时,会创建一个异常对象。我们从这个对象中获取Message
属性并将其打印到控制台。
$ dotnet run An exception occurred Attempted to divide by zero.
C#未捕获的异常
当前上下文中任何未捕获的异常都会传播到更高的上下文,并寻找合适的catch块来处理它。如果找不到任何合适的catch块,.NET运行时的默认机制将终止整个程序的执行。
int x = 100; int y = 0; int z = x / y; Console.WriteLine(z);
在这个程序中,我们除以零。没有自定义异常处理。
$ dotnet run Unhandled exception. System.DivideByZeroException: Attempted to divide by zero. ...
C#编译器给出上述错误信息。
C#IO异常
发生I/O错误时抛出IOException
。在下面的示例中,我们读取文件的内容。
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
关键字后面的语句。它通常用于清理任务,例如关闭文件或清除缓冲区。
} catch (IOException e) { Console.WriteLine("IO Error"); Console.WriteLine(e.Message); }
在这种情况下,我们捕获特定的IOException
异常。
} finally { Console.WriteLine("Inside finally block"); if (fs != null) { fs.Close(); } }
这些行保证文件处理程序已关闭。
$ cat langs.txt C# Java Python Ruby PHP JavaScript
这些是langs.txt
文件的内容。
$ dotnet run C# Java Python Ruby PHP JavaScript Inside finally block
C#多个异常
我们经常需要处理多个异常。
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); }
在这个例子中,我们捕获了各种异常。请注意,更具体的异常应该在通用异常之前。我们从控制台读取两个数字,并检查零除法错误和错误的数字格式。
$ dotnet run Enter first number: we Wrong format of number. Input string was not in a correct format.
C#自定义异常
自定义异常是派生自System.Exception
类的用户定义的异常类。
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); } class BigValueException : Exception { public BigValueException(string msg) : base(msg) { } }
我们假设我们遇到了无法处理大数字的情况。
class BigValueException : Exception
我们有一个BigValueException
类。此类派生自内置的Exception
类。
const int LIMIT = 333;
我们的程序认为大于这个常量的数字是“大”的。
public BigValueException(string msg) : base(msg) {}
在构造器内部,我们调用父级的构造器。我们将消息传递给父母。
if (x > LIMIT) { throw new BigValueException("Exceeded the maximum value"); }
如果值大于限制,我们将抛出自定义异常。我们给异常一条消息“超出最大值”。
} catch (BigValueException e) { Console.WriteLine(e.Message); }
我们捕获异常并将其消息打印到控制台。
$ dotnet run Exceeded the maximum value
在本文中,我们使用C#处理异常。
列出所有C#教程。