嵌套 if 语句是否可提高性能或比平面 if 语句具有其他优势
本文关键字:if 语句 其他 平面 是否 高性能 嵌套 | 更新日期: 2023-09-27 18:32:42
我有一系列有点笨拙的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
}
这样做的明显缺点是我多次重新检查条件。在这种情况下,它是如此之小,我无法想象它有任何区别,但我的问题是:
- C#、Java 等的现代编译器能否/是否优化第二个示例以消除重复检查?这在本例中很好,但如果条件检查也有副作用,则可能会导致问题。
- 另外,一般来说,哪种方法会更受欢迎?
AND 语句
将被 C# 中的编译器快捷方式,因此如果 direction.x <= 0,则 else if 语句中的第二个子句不会被计算,因此无需在 "direction> 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;
...
}
我倾向于第一种方法,因为它减少了代码重复(除此之外,它可能稍微快一些 - 在属性volatile
的情况下,变量必须重新读取(。
如果您需要将direction.x < 0
条件更改为direction.x > 1
,会发生什么(可能不是这里最好的例子,但您明白了......您只需在一个地方更改它。
此外,我认为第一种方法更容易理解:当您遵循代码时,您知道如果您在if
语句的第一个分支中,它"不能与右冲突",而使用第二种方法,您始终必须仔细考虑整个条件,以及前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;
}