嵌套if语句是否可以提高性能,还是比if语句更具优势?

时间:2014-12-02 10:49:32

标签: java c# if-statement optimization compilation

我有一些略显笨拙的if语句,按惯例我这样嵌套:

// Cannot collide with right
    if(direction.x < 0)
    {
        // Cannot collide with top
        if(direction.y < 0)
        {
            // Check left and bottom
        }
        // Cannot collide with bottom
        else if (direction.y > 0)
        {
            // Check left and top
        }
        // Cannot collide with top or bottom
        else
        {
            // Check left only

        }
    }
    // Cannot collide with left
    else if (direction.x > 0)
    {
        // Cannot collide with top
        if(direction.y < 0)
        {
            // Check right and bottom
        }
        // Cannot collide with bottom
        else if (direction.y > 0)
        {
            // Check right and top
        }
        // Cannot collide with top or bottom
        else
        {
            // Check right only

        }
    }

但是我发现它有点难以阅读并且认为它可能更容易作为一组if语句来跟随,有点像开关:

// Cannot collide with right or top
    if(direction.x < 0 && direction.y < 0)
    {
        // Check left and bottom
    }
    // Cannot collide with right or bottom
    else if(direction.x < 0 && direction.y > 0)
    {
        // Check left and top
    }
    // Cannot collide with right, top or bottom
    else if(direction.x < 0)
    {
        // Check left only
    }
    // Cannot collide with left or top
    else if (direction.x > 0 && direction.y < 0)
    {
        // Check right and bottom
    }
    // Cannot collide with left or bottom
    else if (direction.x > 0 && direction.y > 0)
    {
        // Check right and top
    }
    // Cannot collide with left, top or bottom
    else
    {
        // Check right only
    }

这一点的明显缺点是我多次重新检查病情。在这种情况下它是如此之小,我无法想象它会有什么不同,但我的问题是:

  1. 可以/为C#,Java等现代编译器优化第二个例子来删除重复检查吗? 在这个例子中这没什么问题,但如果条件检查也有副作用,可能会引起问题。
  2. 一般而言,哪种方法会受到青睐?

3 个答案:

答案 0 :(得分:0)

AND语句将由C#中的编译器快捷方式,因此如果direction.x&lt; = 0,则不会评估else if语句中的第二个子句,因此不需要基于“方向&gt; 0“。

答案 1 :(得分:0)

我赞成第一种方法,因为它减少了代码重复(除此之外它可能稍快一些 - 如果volatile属性必须重新读取变量)。

如果您需要将direction.x < 0条件更改为direction.x > 1,可能会发生什么情况(这可能不是最好的例子,但您明白了......)?您只需在一个位置更改它。

此外,我认为第一种方法更容易理解:当您遵循代码时,您知道如果您处于if语句的第一个分支中,那么它就不能与之发生冲突右&#34;而对于第二种方法,你总是要考虑整个条件,并且以前if语句的所有条件,以便知道你是否到达那里。

改进

您的代码可以通过将条件与您想要制作的实际代码分开来实现,只需将其转换为switch

为此,我们将使用这些常量:

static final int LEFT   = 0x01;
static final int RIGHT  = 0x02;
static final int TOP    = 0x10;
static final int BOTTOM = 0x20;

代码:

final int dir = (d.x < 0 ? LEFT : d.x > 0 ? RIGHT  : 0)
              + (d.y < 0 ? TOP  : d.y > 0 ? BOTTOM : 0);

switch (dir) {
case LEFT:           // Check left only
    break;
case RIGHT:          // Check right only
    break;
case LEFT + TOP:     // Check left and top
    break;
case LEFT + BOTTOM:  // Check left and bottom
    break;
case RIGHT + TOP:    // Check right and top
    break;
case RIGHT + BOTTOM: // Check right and bottom
    break;
}

答案 2 :(得分:0)

过早优化是邪恶的。

可读性方面我会做类似

的事情
[Flags]
enum Direction
{
    None = 0,
    Top = 1 << 0,
    Bottom = 1 << 1,
    Left = 1 << 2,
    Right = 1 << 3,
}

然后

var d = (x > 0 ? Direction.Right : (x < 0 ? Direction.Left : Direction.None)) |
    (y > 0 ? Direction.Top : (y < 0 ? Direction.Bottom : Direction.None));
switch(d)
{
    case Direction.Left:
        ...
        break;
    case Direction.Right | Direction.Bottom:
        ...
        break;
    ...
}