通过重新排序优化if语句

时间:2009-01-05 16:53:57

标签: c# optimization

我记得曾经读过一次评估成员的顺序很重要。 如

if (null == myClass)

更好(更快?)然后

if (myClass == null)

是这样的吗? 如果有,有人可以解释如何以及为什么? 如果答案需要语言,则瞄准c# 感谢

8 个答案:

答案 0 :(得分:24)

不,它并不快。这是旧C天的遗物,它避免了像

这样的错误
if(myClass = null) /* accident, sets myClass to null instead of comparing */

所以你总是在左边有常数:

if(null = myClass) /* throws an error at compile time */

然而,在C#中这样做是没有意义的我相信..

答案 1 :(得分:6)

由于需要评估==符号的两边,因此速度并不快。 如果您有多个条件,则适用short circuit规则 这些条件是一个接一个地评估,直到达到确定的答案,直到那时为止 所以,如果你有

if ((a != null) && (someLongCheck()) ...

且a为null,则不会调用someLongCheck()

答案 2 :(得分:5)

嗯,这完全取决于语言和编译器。使用框架附带的C#编译器并不重要,因为IL输出是相同的。这是一个示例例程:

static void Main(string[] args)
{
    // Create the instance.
    MyClass instance = new MyClass();

    if (null == instance)
    {
    }

    if (instance == null)
    {
    }
}

第一次比较的IL如下:

L_0007: ldnull 
L_0008: ldloc.0 
L_0009: ceq 
L_000b: ldc.i4.0 
L_000c: ceq 
L_000e: stloc.1 
L_000f: ldloc.1 
L_0010: brtrue.s L_0014
L_0012: nop 
L_0013: nop

第二个:

L_0014: ldloc.0 
L_0015: ldnull 
L_0016: ceq 
L_0018: ldc.i4.0 
L_0019: ceq 
L_001b: stloc.1 
L_001c: ldloc.1 
L_001d: brtrue.s L_0021
L_001f: nop 
L_0020: nop

如您所见,除了堆栈上项目的排序外,输出几乎完全相同。操作是一样的。

如前所述,它是旧C天的遗物,其中0值的任何值都被评估为false,如果你错过了等号,则赋值被评估为条件。

你不必在.NET中担心这一点,因为条件只会接受布尔值,但是如果你要比较true / false,那么将字面值放在第一位可能仍然是更好的编码习惯,所以不要意外评估任务。

答案 3 :(得分:4)

  我记得曾经读过那个订单   评估成员是   重要的。

除了别人所说的之外,我想你还记得在if语句中阅读语句顺序会影响其评价。

由于&&||运算符过载,您可以使用以下指南调整yoru代码以获得更好的性能:

  • 使用&&时,请先订购条件,以便最先出现失败的情况。
  • 使用||时,请先订购条件,以便最先获得成功的条件。

假设您的企业要求您每周一生成TPS报告,您可以编写如下代码:

样品#1:

if (DateTime.Today.DayOfWeek == DayOfWeek.Monday
    && !Database.TpsReportsExist())
{
    // create TpsReports
}

样本#2:

if (!Database.TpsReportsExist()
    && DateTime.Today.DayOfWeek == DayOfWeek.Monday)
{
    // create TpsReports
}

样本1和样本2是等效的,但样本#2对数据库执行查询,无论它是星期几。示例#1避免了不必要的数据库命中,因此我们节省了一些CPU周期和运行时间。

上面的示例很简单,但如果您在紧密循环中执行此类代码,则会在性能上产生巨大差异。

答案 4 :(得分:3)

除非你的编译器真的很笨,否则它不会更快。

这确实意味着如果你不小心输入= not ==你会得到一个编译错误,这就是我认为这个成语来自的地方。

就个人而言,我会说不要在条件中使用作业,并打开编辑警告,告诉你什么时候 - 然后你可以使用 - 对我来说 - 更自然

   if (myClass ==  null)

答案 5 :(得分:1)

不,这没什么区别。把文字放在左边是一个旧的C / C ++编程技巧,当你不小心输入=而不是==时避免痛苦。由于文字不是左值,因此在出错时会出现编译错误。

答案 6 :(得分:1)

据我所知,第一种符号比第二种符号更好,不是出于性能目的,而是为了避免C和C儿童语言中的常见错误:

如果将常量放在==的左侧,将变量放在右侧,编译器将检测您是否键入=代替==。

当你比较两个变量时,这当然不起作用。

答案 7 :(得分:0)

单个评估中的项目顺序(例如您的要求)无关紧要。代码仍然必须解决语句的两个方面,以确定平等或不平等。

我所听到的唯一有利于它的观点是出于可读性,因为眼睛首先看到了预期的价值。我个人认为这种风格难以理解。