csharp:系统关键字:throw

C# 中的 throw 关键字详解

在 C# 编程中,`throw` 关键字用于显式地引发异常。它不仅用于报告错误,还在控制程序流程和异常传播中扮演关键角色。

最基本的形式是抛出一个继承自 `System.Exception` 的对象实例。

public void ValidateUser(string name)
{
    if (name == null)
    {
        // 基础用法:实例化并抛出
        throw new ArgumentNullException(nameof(name), "用户名不能为空");
    }
}

注意:一旦 `throw` 语句执行,当前方法的后续代码将不再运行,控制权将转交给调用堆栈中最近的 `catch` 块。

这是 C# 开发中最容易出错的地方。当你在 `catch` 块中捕获异常并希望将其传递给上层调用者时,有两种写法,但结果截然不同。

使用不带参数的 `throw;` 可以保留原始异常的堆栈跟踪(Stack Trace)。

try
{
    ProcessData();
}
catch (Exception ex)
{
    Log(ex);
    // ✅ 正确:保留原始堆栈信息,就像错误是在 ProcessData 内部发生的一样
    throw; 
}

如果你抛出了捕获的异常变量(`throw ex;`),堆栈跟踪会被重置。

try
{
    ProcessData();
}
catch (Exception ex)
{
    Log(ex);
    // ❌ 错误:堆栈跟踪被重置,看起来错误好像是发生在这行代码,而不是 ProcessData 内部
    throw ex; 
}

从 C# 7.0 开始,`throw` 不仅仅是一个语句,还可以作为一个表达式使用。这意味着你可以在赋值、条件运算符(三元运算符)或 Lambda 表达式中直接使用它。

这是最常见的用法,用于简化参数验证。

public class Person
{
    public string Name { get; }
 
    public Person(string name)
    {
        // 如果 name 为 null,直接抛出异常,否则赋值
        Name = name ?? throw new ArgumentNullException(nameof(name));
    }
}
string GetGrade(int score)
{
    return (score >= 0 && score <= 100) 
        ? (score >= 60 ? "Pass" : "Fail") 
        : throw new ArgumentOutOfRangeException(nameof(score), "分数必须在0到100之间");
}
Func<string, string> cleaner = s => s ?? throw new Exception("字符串不能为null");

在 C# 中使用 `throw` 时,应尽量抛出 .NET 框架提供的标准异常,而不是通用的 `Exception`。

异常类型 适用场景
ArgumentNullException 参数值为 null,但该方法不允许 null。
ArgumentOutOfRangeException 参数值超出了允许的范围(例如索引越界)。
ArgumentException 参数无效,但不属于上述两种情况。
InvalidOperationException 当对象处于不适合执行该方法的状态时(例如在连接关闭时尝试读取数据库)。
NotImplementedException 方法尚未实现(通常用于开发阶段)。
  1. 保留堆栈:在 `catch` 块中重新抛出时,永远使用 `throw;` 而不是 `throw ex;`。
  2. 利用 nameof:在抛出参数相关异常时,使用 `nameof(parameterName)` 来获取参数名,这样重构代码时参数名会自动更新。
    • `throw new ArgumentNullException(nameof(id));`
  3. 不要通过异常控制逻辑:异常应该用于“异常”情况,不要用 `throw` 来做普通的流程跳转(例如跳出循环),这会严重影响性能。
  4. 自定义异常:如果标准异常无法准确描述错误,可以创建继承自 `Exception` 的自定义类。
请输入您的评论. 可以使用维基语法:
 

该主题尚不存在

您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。

  • csharp/系统关键字/throw.txt
  • 最后更改: 2025/12/02 15:12
  • 张叶安