Bil*_*eal 47
无论; 如果一个更快或更好,他们都应该编译成同样的东西.
更重要的是,大多数程序员可能会发现> 0更具可读性,可读性比这样的子微优化更重要.
Mar*_*ers 27
更好的是能够最清楚地表达你意图的那个.
如果您正在测试整数是否在[1,6]范围内,那么您应该将其写为:
if (x >= 1 && x <= 6) { ... }
Run Code Online (Sandbox Code Playgroud)
写这个可行,但不那么明显符合规范:
if (x > 0 && x < 7) { ... }
Run Code Online (Sandbox Code Playgroud)
我也假设你在这里讨论整数类型.如果您正在处理浮点数或十进制数,那么它们不是等价的.
除非您已经分析了代码并发现这是瓶颈,否则您不必担心微观优化.即便如此,在每种情况下检查C#编译器生成的代码以查看它们是否编译为相同的IL都是有趣的.这可以通过使用.NET Reflector来完成.
if (x >= 1)
{
Console.WriteLine("True!");
}
Run Code Online (Sandbox Code Playgroud)
结果是:
L_000b: ldloc.0 // Load the value of x
L_000c: ldc.i4.1 // Load the constant 1
L_000d: blt.s L_0019 // Branch if less than
L_000f: ldstr "True!"
L_0014: call void [mscorlib]System.Console::WriteLine(string)
Run Code Online (Sandbox Code Playgroud)
鉴于:
if (x > 0)
{
Console.WriteLine("True!");
}
Run Code Online (Sandbox Code Playgroud)
得到以下IL:
L_000b: ldloc.0 // Load the value of x
L_000c: ldc.i4.0 // Load the constant 0
L_000d: ble.s L_0019 // Branch if less than or equal
L_000f: ldstr "True!"
L_0014: call void [mscorlib]System.Console::WriteLine(string)
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,编译器都颠倒了比较."大于或等于"测试编译为"小于"指令,"大于"测试编译为"小于或等于".通常,编译器可以自由地进行这样的修改,并且运行不同版本的编译器可能会产生不同的(但等效的)字节码.
鉴于它们没有编译到同一个IL,查看哪个最快的最好方法是在循环中实际运行代码并查看每个版本执行需要多长时间.我试过这样做,但我没有看到编写代码的两种方法之间存在任何可衡量的性能差异.
两者之间的性能差异可以忽略不计(如果有的话).我正在努力证明它可能是什么(它将取决于平台,因为任何不同可能会归结为由JIT发出和执行的代码).
但请记住,性能明智这是极端的微优化很可能是没有根据的.
更好的选择是更具可读性,并在代码中最好地传达您的意图.
我同意其他回应,即通常不应考虑微优化。然而,看看这两个版本中哪一个具有更小/明显_更快的 IL 可能会很有趣。
所以 :
using System;
namespace IL_Test
{
class Program
{
static void Main(string[] args)
{
int i = 3;
if (i > 0)
{
Console.Write("i is greater than zero");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
翻译成:
(调试)
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 i,
[1] bool CS$4$0000)
L_0000: nop
L_0001: ldc.i4.3
L_0002: stloc.0
L_0003: ldloc.0
L_0004: ldc.i4.0
L_0005: cgt
L_0007: ldc.i4.0
L_0008: ceq
L_000a: stloc.1
L_000b: ldloc.1
L_000c: brtrue.s L_001b
L_000e: nop
L_000f: ldstr "i is greater than zero"
L_0014: call void [mscorlib]System.Console::Write(string)
L_0019: nop
L_001a: nop
L_001b: ret
}
Run Code Online (Sandbox Code Playgroud)
(释放)
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 i)
L_0000: ldc.i4.3
L_0001: stloc.0
L_0002: ldloc.0
L_0003: ldc.i4.0
L_0004: ble.s L_0010
L_0006: ldstr "i is greater than zero"
L_000b: call void [mscorlib]System.Console::Write(string)
L_0010: ret
}
Run Code Online (Sandbox Code Playgroud)
尽管
using System;
namespace IL_Test
{
class Program
{
static void Main(string[] args)
{
int i = 3;
if (i >= 1)
{
Console.Write("i is greater than zero");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
进入
(调试)
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 i,
[1] bool CS$4$0000)
L_0000: nop
L_0001: ldc.i4.3
L_0002: stloc.0
L_0003: ldloc.0
L_0004: ldc.i4.1
L_0005: clt
L_0007: stloc.1
L_0008: ldloc.1
L_0009: brtrue.s L_0018
L_000b: nop
L_000c: ldstr "i is greater than zero"
L_0011: call void [mscorlib]System.Console::Write(string)
L_0016: nop
L_0017: nop
L_0018: ret
}
Run Code Online (Sandbox Code Playgroud)
(释放)
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 i)
L_0000: ldc.i4.3
L_0001: stloc.0
L_0002: ldloc.0
L_0003: ldc.i4.1
L_0004: blt.s L_0010
L_0006: ldstr "i is greater than zero"
L_000b: call void [mscorlib]System.Console::Write(string)
L_0010: ret
}
Run Code Online (Sandbox Code Playgroud)
据我所知,在调试模式下, i>=1 比 i>0 略快
在发布模式下,所有差异都在偏移 0004 处,BLE 与 BLT。我想这两个 IL 操作转化为同样消耗 CPU 的本机操作..