【问题标题】:Performance advantage of discard operator丢弃算子的性能优势
【发布时间】:2020-05-02 20:55:33
【问题描述】:

假设我的 C# 应用中有这个:

try{
    Somethrowingmethod();
}catch(Exception ex){
    throw new Exception("oops");
}

如果我保持我的代码不变,编译器会(理所当然地)抱怨我声明了 ex 但没有使用它。

所以我应该这样做:

try{
    Somethrowingmethod();
}catch(Exception _){
    throw new Exception("oops");
}

我的问题是,执行此操作后是否会提高性能?

还是只是为了干净的代码实践?

【问题讨论】:

  • 干净的代码,这意味着您已经声明您打算丢弃异常。如果您不需要引用它,您可以只捕获异常而不声明它,但整个想法是显示异常链/堆栈,而不是仅仅抛出一个新异常并丢弃堆栈信息。这样做需要有充分的理由。
  • 这声明了一个名为Exception 的变量_。这不是丢弃,并且应该针对未使用的变量发出相同的compiler warning。你可以catch(Exception){ } 或者因为这无论如何都是一个问题,只是catch { },但你并没有从它们中获得任何性能提升。
  • 不仅在本例中使用_,在解析int.TryParse("foo", out _) 时也只是一个语法糖。编译器会自动创建一个变量等,但它不会以任何方式影响性能
  • 在这个例子中使用_ 并不是放弃,所以不涉及语法糖。仅捕获异常类型是此处“丢弃”的正确方法,并且不会创建变量。但仍然没有从中获得性能提升。
  • 编译器确实抱怨这段代码。有一个代码分析规则对它提出建议,从 ex 下面的绿色曲线可见,应该告诉你根本不需要 ex。对那条摇摆狗的尾巴要小心一点。当您编写 try/catch-em-all/throw-something-else 代码时,在调试程序时让 ex 进行检查非常重要。你不应该写,但分析功能不够聪明,无法告诉你。

标签: c# variables


【解决方案1】:

您的问题有缺陷,因为您的示例不涉及丢弃。相反,它将Exception 变量命名为_,并且仍应为未使用的变量发出相同的警告。请参阅 this SharpLab 示例并查看警告和生成的 IL 的 .locals init

.locals init (
  [0] class [System.Private.CoreLib]System.Exception
)

“丢弃”异常的正确方法是仅捕获 type

try {
  DoSomething();
} catch (Exception) {
  //... 
} 

这并没有声明一个局部变量,您可以在上面的链接中通过删除_ 并查看更新的.locals init 部分来验证它(提示:它现在已经消失了)。

由于这是捕获基本异常类型,您也可以将其重写为:

try {
  DoSomething();
} catch {
  //... 
} 

但是请注意,通常捕获所有/捕获基本 Exception 类型是一个坏主意。

回到您最初的询问:在任何这些情况下都不会提高性能。 充其量一个变量被省略了,但是一个 true 丢弃只是语法糖并且仍然声明​​了一个变量。这段代码:

int.TryParse("1", out _);

仍然涉及int 类型的局部变量。您可以通过查看same section of the IL 看到这一点。

.locals init (
  [0] int32
)

但同样没有性能提升。

【讨论】:

  • 感谢您的回答。这是超级澄清。
【解决方案2】:

或者干脆这样做

try{
    Somethrowingmethod();
}catch(Exception){
    throw new Exception("oops");
}

但没有性能差异

【讨论】:

    猜你喜欢
    • 2010-10-20
    • 2011-03-21
    • 2010-10-12
    • 2015-01-06
    • 2015-04-12
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多