C# 为什么ReSharper为C代码反转IFs?它是否能提供更好的性能(甚至稍微)?

C# 为什么ReSharper为C代码反转IFs?它是否能提供更好的性能(甚至稍微)?,c#,C#,考虑以下代码示例: private void AddEnvelope(MailMessage mail) { if (this.CopyEnvelope) { // Perform a few operations } } vs 底层代码的执行速度会更快吗?为什么会提出这一建议 更新 考虑过这个问题,有些人可能会觉得答案很明显。但是我们很多开发人员从来没有习惯于首先嵌套if语句…更新的答案: 这是一个代码可维护性建议。比将其余代码嵌套在IF语句中更易于阅

考虑以下代码示例:

private void AddEnvelope(MailMessage mail)
{
    if (this.CopyEnvelope)
    {
        // Perform a few operations
    }
}
vs

底层代码的执行速度会更快吗?为什么会提出这一建议

更新


考虑过这个问题,有些人可能会觉得答案很明显。但是我们很多开发人员从来没有习惯于首先嵌套
if
语句…

更新的答案:

这是一个代码可维护性建议。比将其余代码嵌套在IF语句中更易于阅读。有关这方面的示例/讨论,请参见以下链接:

  • “遗留要求声明”部分
原始答案:

实际上,由于必须执行一个测试,它的运行速度会慢一些(可以忽略不计) 不是手术

事实上,有些人实际上认为更漂亮的方法是 代码,因为它避免了对大部分文件进行额外的缩进 代码


没关系。停止为根本不存在的性能问题而苦恼——使用探查器来识别代码中确实存在问题的区域,并修复它们。主动优化-在您知道存在问题之前-顾名思义是浪费时间

这种“优化”不值得花时间重构代码,因为所有现代编译器都已经进行了足够小的优化,使得这种技巧变得微不足道。
如上所述,性能优化是通过探查器来完成的,在应用性能修复之前,计算系统的性能如何以及潜在的瓶颈,然后在性能修复之后,查看您的修复是否良好

它是一个条件的重构,将整个方法内容包含到一个对象中。这与优化无关。

我喜欢关于优化这类事情的评论,再多加一点

我能想到的唯一一次优化if语句是当您有两个或更多长时间运行的方法的结果时,需要将这些方法组合起来以确定是否要执行其他操作。如果第一个操作产生的结果将通过条件,则您只希望执行第二个操作。通常,将最有可能返回false的一个放在第一位将是一个更明智的选择。这是因为如果它为false,则根本不会对第二个进行计算。再次强调,如果操作是重要的,并且您可以预测哪个更可能通过或失败,那么只值得担心。将此反转为或。。。如果为真,它将只评估第一个,并以这种方式进行优化。 i、 e

不如

if (ThisOneUsuallyFails() && ThisOneUsuallyPasses())
因为只有在奇怪的情况下,第一种方法才有效,所以你必须看看第二种方法。你可以从中得到一些其他的味道,但我认为你应该明白这一点

如果担心性能问题,最好是担心如何使用字符串、集合、为数据库编制索引和分配对象,而不是花大量时间担心单个条件if语句

一般来说,您给出的底层代码将为您提供一个避免if语句中出现大量代码块的机会,这可能会导致愚蠢的打字错误。传统的想法是,为了避免不同类型的编码错误,您应该只从一个方法返回一个点。当前的想法(至少是一些工具供应商,如jetbrains resharper等)似乎是在条件语句中封装最少的代码更好。任何超过这一点的内容都是主观的,所以我就到此为止。

必读:

圈复杂度是对线性无关的圈数的定量度量 通过程序源代码的路径

这意味着,每次使用and
if
语句进行分支时,圈复杂度增加1

通过程序测试每个线性独立的路径;在这种情况下,测试用例的数量将等于程序的圈复杂度

这意味着,如果您想完全测试代码,那么对于每个
if
语句,您必须引入一个新的测试用例

因此,通过引入更多的if语句,代码的复杂性会增加,测试它所需的测试用例数量也会增加


通过删除
if
语句,您的代码复杂性会降低,测试所需的测试用例数量也会降低。

这是一个重新精简的建议。老实说,我更看重的是性能,而不是漂亮的代码……是的,这里的区别在于它是否在执行一个程序。不过,这样做的好处是,嵌套级别减少了1级,这可能会根据具体情况提高可读性。@JL:这是一个过早的微优化,让我感到困惑。除非您已经证明存在性能问题,否则易读、易于维护的代码应该始终是优先考虑的。请看Alex的答案()——这是正确的。@JL:不要担心这里的性能,结果几乎相同。这与我假设的执行
if(myBool==false)
if(!myBool)的性能差异相同。为什么必须执行NOT操作?假设使用x86CPU,则应将其编译为类似于比较指令(cmp)的内容,然后再编译为相等跳转指令或不相等跳转指令(je/jne)。两条指令,任意一条。由于分支预测的原因,可能会有一个小的差异,但这两种情况都很容易发生。+1。亚历克斯,你听着,JL。首先是可读性和可维护性代码。如果你发现了一个缓慢的地方,那么就着手研究“聪明”代码的技巧。事实上,我正试图对语言基础有更深入的理解。同时,我也在玩reSharper,当它做出改变或推荐时,我想知道它背后的逻辑
if (ThisOneUsuallyPasses() && ThisOneUsuallyFails())
if (ThisOneUsuallyFails() && ThisOneUsuallyPasses())