C# 通过 try/catch/finally 捕获的异常来处理错误。正确的异常处理意味着捕获特定的异常类型、清理资源(通常使用 using)、创建有意义的自定义异常,以及不要静默吞掉错误。
try
{
var data = RiskyOperation();
}
catch (FileNotFoundException ex) // catch SPECIFIC types (most specific first)
{
Console.WriteLine($"File missing: {ex.Message}");
}
catch (IOException ex)
{
Log(ex);
throw; // re-throw, PRESERVING the stack trace (not `throw ex`)
}
catch (Exception ex) // catch-all (last) — base of all exceptions
{
Log(ex);
}
finally
{
Cleanup(); // ALWAYS runs (success, exception, or return)
}
首先捕获特定的异常类型,使用 Exception 作为最终的通用捕获器,并使用 finally 进行必须始终运行的清理。重要: 使用 throw;(而不是 throw ex;)重新抛出——它保留了原始堆栈跟踪。
if (amount < 0)
throw new ArgumentException("Amount must be positive", nameof(amount));
// a custom exception for your domain
public class InsufficientFundsException : Exception
{
public InsufficientFundsException(string message) : base(message) { }
}
throw new InsufficientFundsException("Balance too low");
// `using` guarantees Dispose() is called (close files/connections) even on exception
using (var file = new StreamReader("data.txt"))
{
var content = file.ReadToEnd();
} // file.Dispose() called automatically here
using var conn = new SqlConnection(...); // C# 8 simplified form
using 语句确保 IDisposable 资源(文件、连接)被正确处理——处理资源清理的首选方式,比手动 finally 更可靠。
catch (Exception ex) when (ex.Message.Contains("timeout")) // exception filter (when)
{ ... }
✓ Catch SPECIFIC exceptions, not just Exception
✓ Use `using` for IDisposable resources (reliable cleanup)
✓ Don't swallow exceptions silently (empty catch) — log or re-throw
✓ Use `throw;` (not `throw ex;`) to preserve the stack trace
✓ Create meaningful custom exceptions; don't use exceptions for normal control flow
正确的异常处理对于构建健壮、可靠的 C# 应用程序至关重要,因此深入理解它很重要。
try/catch/finally 结构、捕获特定的异常类型(用于有针对性的处理)以及使用 Exception 作为最终的通用捕获器,并在 finally 中进行保证的清理是基础。
几个 C# 特定的最佳实践特别重要:重新抛出时使用**throw; 而不是 throw ex;(这是一个微妙但至关重要的细节——throw ex; 重置堆栈跟踪,丢失宝贵的调试信息),对 IDisposable 资源使用using 语句**(首选的、可靠的方式来确保文件、连接和其他资源即使在异常发生时也得到正确清理——比手动 finally 块更健壮,也是 C# 资源管理模型的核心),以及不要静默吞掉异常。
理解异常处理——结构、特定的捕获、自定义异常、保留堆栈跟踪的重新抛出,尤其是用于资源清理的 using——对于编写可靠的 C# 很重要,这样可以优雅地处理错误并正确管理资源。
由于未处理的异常和资源泄漏会导致真正的可靠性问题,而且由于 C# 具有特定的习语(using 模式、throw; 保留)来区分健壮代码和脆弱代码,掌握异常处理对于专业 C# 开发来说是重要的、常应用的知识。