try-catch语句 #

一、try-catch基本语法 #

1.1 基本结构 #

csharp
try
{
}
catch (Exception ex)
{
}

1.2 简单示例 #

csharp
try
{
    int result = 10 / 0;
    Console.WriteLine(result);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine($"除零错误:{ex.Message}");
}

二、多重catch #

2.1 捕获多种异常 #

csharp
try
{
    string content = File.ReadAllText("config.txt");
    int value = int.Parse(content);
    Console.WriteLine(value);
}
catch (FileNotFoundException ex)
{
    Console.WriteLine($"文件未找到:{ex.FileName}");
}
catch (FormatException ex)
{
    Console.WriteLine($"格式错误:{ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"其他错误:{ex.Message}");
}

2.2 catch顺序 #

csharp
try
{
}
catch (ArgumentNullException ex)
{
}
catch (ArgumentException ex)
{
}
catch (Exception ex)
{
}

2.3 不带变量的catch #

csharp
try
{
}
catch (DivideByZeroException)
{
    Console.WriteLine("除零错误");
}
catch
{
    Console.WriteLine("未知错误");
}

三、finally块 #

3.1 基本用法 #

csharp
FileStream stream = null;
try
{
    stream = File.OpenRead("data.txt");
}
catch (IOException ex)
{
    Console.WriteLine($"读取错误:{ex.Message}");
}
finally
{
    stream?.Dispose();
}

3.2 finally特点 #

  • 始终执行
  • 无论是否发生异常
  • 即使try中有return
csharp
public int TestFinally()
{
    try
    {
        Console.WriteLine("try");
        return 1;
    }
    finally
    {
        Console.WriteLine("finally");
    }
}

3.3 using语句替代 #

csharp
try
{
    using var stream = File.OpenRead("data.txt");
}
catch (IOException ex)
{
    Console.WriteLine($"读取错误:{ex.Message}");
}

四、异常过滤器 #

4.1 when关键字 #

csharp
try
{
    ProcessData(data);
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
{
    Console.WriteLine($"文件操作错误:{ex.Message}");
}
catch (Exception ex) when (ex.Message.Contains("timeout"))
{
    Console.WriteLine($"超时错误:{ex.Message}");
}

4.2 条件过滤 #

csharp
try
{
    int result = int.Parse(input);
}
catch (FormatException ex) when (input == null)
{
    Console.WriteLine("输入为空");
}
catch (FormatException ex) when (input.Length == 0)
{
    Console.WriteLine("输入为空字符串");
}
catch (FormatException ex)
{
    Console.WriteLine($"格式错误:{ex.Message}");
}

4.3 日志记录 #

csharp
try
{
    ProcessData(data);
}
catch (Exception ex) when (LogError(ex))
{
    throw;
}

private static bool LogError(Exception ex)
{
    Logger.Error(ex);
    return false;
}

五、异常重新抛出 #

5.1 throw #

csharp
try
{
    ProcessData(data);
}
catch (Exception ex)
{
    Log(ex);
    throw;
}

5.2 throw ex #

csharp
try
{
    ProcessData(data);
}
catch (Exception ex)
{
    Log(ex);
    throw ex;
}

5.3 包装异常 #

csharp
try
{
    ProcessData(data);
}
catch (Exception ex)
{
    throw new DataProcessingException("数据处理失败", ex);
}

六、嵌套try-catch #

6.1 嵌套结构 #

csharp
try
{
    try
    {
        ProcessData(data);
    }
    catch (FormatException ex)
    {
        Console.WriteLine($"格式错误:{ex.Message}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"外层错误:{ex.Message}");
}

6.2 方法调用链 #

csharp
public void MethodA()
{
    try
    {
        MethodB();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"MethodA捕获:{ex.Message}");
    }
}

public void MethodB()
{
    try
    {
        MethodC();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"MethodB捕获:{ex.Message}");
        throw;
    }
}

public void MethodC()
{
    throw new Exception("MethodC错误");
}

七、实战示例 #

7.1 文件处理 #

csharp
public string SafeReadFile(string path)
{
    try
    {
        return File.ReadAllText(path);
    }
    catch (FileNotFoundException)
    {
        return null;
    }
    catch (UnauthorizedAccessException ex)
    {
        Logger.Warning($"无权限访问文件:{path}");
        return null;
    }
    catch (IOException ex)
    {
        Logger.Error($"读取文件失败:{ex.Message}");
        throw;
    }
}

7.2 数据库操作 #

csharp
public async Task<User> GetUserAsync(int id)
{
    try
    {
        using var connection = new SqlConnection(_connectionString);
        await connection.OpenAsync();
        
        var sql = "SELECT * FROM Users WHERE Id = @Id";
        return await connection.QueryFirstOrDefaultAsync<User>(sql, new { Id = id });
    }
    catch (SqlException ex) when (ex.Number == 208)
    {
        throw new InvalidOperationException("表不存在", ex);
    }
    catch (SqlException ex) when (ex.Number == 547)
    {
        throw new InvalidOperationException("外键约束错误", ex);
    }
    catch (SqlException ex)
    {
        Logger.Error($"数据库错误:{ex.Message}");
        throw new DataAccessException("获取用户失败", ex);
    }
}

7.3 API调用 #

csharp
public async Task<T> GetAsync<T>(string url)
{
    try
    {
        using var client = new HttpClient();
        var response = await client.GetAsync(url);
        response.EnsureSuccessStatusCode();
        
        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<T>(json);
    }
    catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
    {
        return default;
    }
    catch (HttpRequestException ex)
    {
        Logger.Error($"HTTP请求失败:{ex.Message}");
        throw;
    }
    catch (JsonException ex)
    {
        Logger.Error($"JSON解析失败:{ex.Message}");
        throw new DataFormatException("数据格式错误", ex);
    }
}

八、最佳实践 #

8.1 捕获特定异常 #

csharp
try
{
    File.ReadAllText(path);
}
catch (IOException ex)
{
}
catch (Exception ex)
{
}

8.2 不要捕获所有异常 #

csharp
try
{
}
catch (Exception)
{
}

8.3 使用using释放资源 #

csharp
using var stream = File.OpenRead(path);
using var reader = new StreamReader(stream);

九、总结 #

try-catch要点:

要点 说明
try 可能出错的代码
catch 异常处理
finally 始终执行
when 异常过滤器
throw 重新抛出

下一步,让我们学习自定义异常!

最后更新:2026-03-26