gpt4 book ai didi

c# - 为什么C#有一个单独的重新抛出语句( throw; )而不是重载 throw ex ?

转载 作者:行者123 更新时间:2023-12-02 15:32:22 25 4
gpt4 key购买 nike

抛出异常时,保留堆栈跟踪是最常见的期望行为,在 Java 中,这可以通过 throw ex; 获得,但在 C# 中,throw; 必须使用。 (另请注意,许多 C# 程序员经常错误地使用 throw ex; 而不是 throw;)。

如果有时必须清除堆栈跟踪(这是一种不太常见的情况),则可以抛出一个新的异常,例如 throw new MyException(ex.Message, otherDetails);

那么,考虑到上述情况,在 C# 中使用单独的 throw; 语句的优点是什么?

或者,换句话说:为什么 C# 对于最常用的情况(当用户想要保留堆栈跟踪时)使用一个特殊的单独语句 (throw;),这是鲜为人知的,对于不太常见的情况(当堆栈跟踪被清除时),它使用更自然的 throw ex; ?还有我没有提到的其他可能的用例吗?

C# 和 Java 代码示例:

// This is the C# design
try
{
//...
}
catch (MyException ex)
{
// rethrow so that stack trace is preserved
ex.AppendData(contextVariable);
throw;
}
catch (PrivateException ex)
{
// throw new exception so stack trace is not preserved
throw new PublicException(ex.Message);
}


// This is the Java design
try
{
//...
}
catch (MyException ex)
{
// rethrow so that stack trace is preserved
ex.AppendData(contextVariable);
throw ex;
// and I can even choose to use something like, where ProcessException(ex) will return the same ex
throw ProcessException(ex, contextVariable);
}
catch (PrivateException ex)
{
// throw new so stack trace is not preserved
throw new PublicException(ex.getMessage());
}

最佳答案

两者都抛出变体的原因

catch (SomeExceptionType ex)
{
frobnicate(ex);
throw;
throw ex;
}

存在是因为每个都有用例。只有第一个对于调试发生异常的代码有用,但在成熟的库中,几乎可以肯定原因是库外部的(硬件/操作系统环境中的故障​​,或者由消费者传递的错误参数)图书馆)。在这种情况下,库内部的详细信息对使用该库的程序员没有帮助,实际上可能会造成更多困惑。

此外,闭源库,尤其是通过 SaaS 模型远程访问的库1(Web 服务)可能不希望公开实现细节,因为这些细节可能包含专有知识产权。在这种情况下,throw ex; 是更好的选择。

您说 Java throw ex; 保留现有的堆栈跟踪。这样的语言如何避免信息泄露呢?必须对除堆栈跟踪之外的所有内容进行深层复制到新的异常对象,当引发更多派生类型的异常时,这一点尤其困难。 C# 的选择使得这两种行为都非常容易实现。

(您可能仍希望执行过滤的深度复制,以防信息在其他异常属性(例如 InnerException)中泄漏。但如果您愿意,C# 允许您跳过复制步骤。)

1 本地库的实现细节可以通过其他方式发现。保护这些细节requires a webservice-like execution model ,保持对代码的完全控制。

关于c# - 为什么C#有一个单独的重新抛出语句( throw; )而不是重载 throw ex ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24249565/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com