[原译]C#中的throw

本文介绍了C#中的异常处理机制,详细解释了如何使用throw语句重新抛出异常或创建新异常,并展示了不同类型的throw语句如何影响异常的StackTrace。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Throw会抛出/传递异常,通过在catch块里使用throw语句.可以改变产生的异常,比如我们可以抛出一个新的异常,throw语句有各种各样的,并且很有必要.

例子
我们首先看一下三个方法,分别叫做A,B,C,他们使用不同的throw语句。方法A使用了无参的throw语句。这可以被看作是rethrow(继续抛出)—他会抛出已经出现的同样的异常

继续,方法B throw一个命名的异常变量。这就不是一个完全的rethrow了—因为他虽然抛出了同样的异常。但是改变了StackTrace(堆栈轨迹),如果有必要的话,我们可以收集一些异常信息,而方法C则创建了一个新的异常。
提示:你可以通过这种方法实现自定义的的错误处理
使用throw语句的例子

using System;
class Program
{
    static void Main()
    {
    try
    {
        A();
        B();
        C(null);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
    }

    static void A()
    {
    // Rethrow 语法.
    try
    {
        int value = 1 / int.Parse("0");
    }
    catch
    {
        throw;
    }
    }

    static void B()
    {
    // 过滤异常类型.
    try
    {
        int value = 1 / int.Parse("0");
    }
    catch (DivideByZeroException ex)
    {
        throw ex;
    }
    }

    static void C(string value)
    {
    // 创建新的异常.
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }
    }
}

 

程序可能的输出结果

System.DivideByZeroException: Attempted to divide by zero.
System.DivideByZeroException: Attempted to divide by zero.
System.ArgumentNullException: Value cannot be null.
Parameter name: value

 

Rethrow

接着我们看更多的关于rethrows的细节。Rethrow必须是一个无参的throw语句。如果使用throw ex,那么TargetSie(TargetSite 从堆栈跟踪中获取抛出该异常的方法。如果堆栈跟踪为空引用,TargetSite 也返回空引用。-译者注)和StackTrace都被改变了。

在下面的程序里,X()方法使用了rethrow语句。Y()使用了throw ex语句。我们可以看看当rethrow语句使用的使用,引发异常的方法,也就是异常的TargetSite是在StringToNumber---一个int.Parse内部的方法。

但是:当throw ex用的时候。就像在Y()里面,这个异常的TargetSite被修改到了当前的Y()方法里。
测试rethrow的例子

using System;

class Program
{
    static void Main()
    {
    try
    {
        X();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.TargetSite);
    }

    try
    {
        Y();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.TargetSite);
    }
    }

    static void X()
    {
    try
    {
        int.Parse("?");
    }
    catch (Exception)
    {
        throw; // [Rethrow 构造]
    }
    }

    static void Y()
    {
    try
    {
        int.Parse("?");
    }
    catch (Exception ex)
    {
        throw ex; // [Throw 捕获的ex变量]
    }
    }
}

 

输出

Void StringToNumber(System.String, ...)
Void Y()

 

总结:
异常处理机制提供了可选的控制路径,它将异常逻辑和异常处理分割开来。并且可以通过throw来rethrow异常或是生成一个新的异常。
译自:http://www.dotnetperls.com/throw

本文由Bystander翻译,转载请注明http://leaver.me

转载于:https://www.cnblogs.com/lazycoding/archive/2012/11/18/2775785.html

03-20
<think>好的,用户想了解C#throw关键字的用法和示例。我需要先回忆一下throw的基本作用,然后整理常见的使用场景和注意事项。 首先,throw用于在程序中主动抛出异常,这通常在错误发生时用来中断当前流程,并将异常传递给调用堆栈。用户可能需要知道基本语法,比如throw new Exception("message")。 然后,应该区分不同情况,比如抛出系统异常、自定义异常,或者重新抛出异常(throw ex和throw的区别)。这里要注意,重新抛出异常时使用throw而不是throw ex,以保留原始堆栈信息。 另外,C# 7.0引入了表达式形式的throw,可以在表达式内部使用,比如条件运算符中,这可能是一个有用的知识点,需要举例说明。 用户可能还关心异常处理的最佳实践,比如何时应该抛出异常,何时应该捕获。还有可能涉及到throw在异步方法中的使用,比如在async方法中抛出异常的行为是否有所不同。 需要检查是否有相关的引用内容可以支持回答。例如,引用[2]提到在异步Maybe中使用await时抛出异常的情况,这可能与throw在异步环境中的处理有关,可以适当引用。 还要考虑用户可能的后续问题,比如性能影响、自定义异常创建、异常过滤等,提前准备相关问题供用户参考。 最后,确保回答结构清晰,分点说明用法,提供代码示例,并注意LaTeX格式的正确使用,比如行内公式用$...$,独立公式用$$...$$,但这里可能用不上数学公式,但需要遵循用户的其他格式要求,比如中文回答,引用标识等。</think>### C#throw关键字的用途与示例 #### 一、核心作用 `throw`关键字用于**主动抛出异常**,强制中断当前代码流程并将异常传递给调用堆栈。其典型应用场景包括: 1. 参数验证失败时抛出$ArgumentException$[^1] 2. 对象状态异常时抛出$InvalidOperationException$ 3. 自定义业务规则校验失败 #### 二、基础语法形式 ```csharp // 抛出新异常 throw new Exception("Error message"); // 重新抛出当前捕获的异常(保留原始堆栈信息) try { /* ... */ } catch (Exception ex) { throw; } // 抛出特定类型异常 throw new FileNotFoundException("config.json not found"); ``` #### 三、进阶用法 1. **表达式抛出(C# 7.0+)** ```csharp var config = LoadConfig() ?? throw new ConfigLoadException(); ``` 2. **异常过滤器(C# 6.0+)** ```csharp try { /* ... */ } catch (HttpRequestException ex) when (ex.StatusCode == 404) { throw new ResourceNotFoundException(); } ``` 3. **异步方法中的异常传播** ```csharp public async Task ProcessDataAsync() { if (!ValidateInput()) throw new InvalidDataException("Input validation failed"); // 异常会包装在Task中传递[^2] } ``` #### 四、最佳实践 1. 优先使用预定义异常类型(如$ArgumentNullException$) 2. 抛出异常前确保释放非托管资源(参考$IDisposable$模式[^1]) 3. 避免使用`throw ex`会破坏调用堆栈信息 4. 每个异常应包含清晰的错误描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值