有人可以告诉我以下哪两个片段有效/推荐以及为什么?
private void method1()
{
if(condition)
{
//some code to be executed when the condition is met
return;
}
//some code to be executed when the condition is not met
}
private void method2()
{
if(condition)
{
//some code to be executed when the condition is met
}
else
{
//some code to be executed when the condition is not met
}
}
以下问题中给出的答案在效率或推荐实践方面没有提到任何与我的问题有关的问题,问题看起来只是在询问什么是正确的。
答案 0 :(得分:2)
就执行速度而言,可能不会有任何值得思考的差异。
就可读性而言,我建议你将问题放在另一个层面,看看它在哪里。这两个例子遵循你的两个模式,但是对于一个不那么微不足道的问题。哪个更容易阅读?
void Example1()
{
if (a)
{
if (b)
{
if (c)
{
D();
}
}
else
{
Y();
}
}
else
{
X();
}
}
void Example2()
{
if (!a)
{
X();
return;
}
if (!b)
{
Y();
return;
}
if (!c) return;
D();
}
第一个模式最终会使用Arrow,而第二个模式会使用Guard。箭头被认为是一种反模式。
当你展平箭头以使用守卫时,你减少cyclomatic complexity,减少代码长度,减少滚动查看完整代码块的需要,并减少理解其含义所需的心理操作次数平均代码行。
第二种方法在几乎所有方面都是客观上更好的,除了非常简单的逻辑之外,else
可以更清楚地传达你想要完成的事情。
答案 1 :(得分:2)
性能完全没有区别。在IL中比较这两种方法:
.method private hidebysig static void Method1() cil managed
{
//
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::condition // Push condition onto stack
IL_0006: ldc.i4.1 // Load constant integer 1
IL_0007: ceq // Check if they equal
IL_0009: ldc.i4.0 // Load constant integer 0
IL_000a: ceq // Check if previous compare returned true
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: brtrue.s IL_0013 // If true then short branch to return
IL_0010: nop
IL_0011: br.s IL_0013 // Else just to return (the same as IL_000e)
IL_0013: ret
} // end of method Program::Method1
.method private hidebysig static void Method2() cil managed
{
//
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::condition
IL_0006: ldc.i4.1
IL_0007: ceq
IL_0009: ldc.i4.0
IL_000a: ceq
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: brtrue.s IL_0014
IL_0010: nop
IL_0011: nop
IL_0012: br.s IL_0016 // We branch but in release I doubt the branch would still exist at runtime.
IL_0014: nop
IL_0015: nop
IL_0016: ret
} // end of method Program::Method2
这些nop
指令仅可见,因为我在调试模式下运行它。它们不会在发布中存在。可复制的代码:
public static void Main(string[] args)
{
Method1();
Method2();
}
static int condition = 1;
private static void Method1()
{
if(condition == 1)
{
return;
}
}
private static void Method2()
{
if(condition == 1)
{
}
else
{
}
}
在优化应用程序时,首先要看一下真正的瓶颈是什么。找出导致最长延迟的原因并开始优化。您目前要做的是称为过早优化。因此,您的代码变得不那么可读,可能更慢并且更容易出错。
答案 2 :(得分:1)
如果您有 MSIL强迫症(强迫症),您可以通过不使用OpCodes.Nop
来保存自己1 else
!
如果修补了操作码,则填充空格。没有有意义的操作 虽然可以消耗处理周期,但仍会执行。
<强>代码强>
private static int Method1(bool condition)
{
if (condition)
{
return 1+1;
}
return 2 + 2;
}
<强> MSIL 强>
IL_0000: nop
IL_0001: ldarg.0 // condition
IL_0002: stloc.0 // V_0
IL_0003: ldloc.0 // V_0
IL_0004: brfalse.s IL_000b
IL_0006: nop
IL_0007: ldc.i4.2
IL_0008: stloc.1 // V_1
IL_0009: br.s IL_000f
IL_000b: ldc.i4.4
IL_000c: stloc.1 // V_1
IL_000d: br.s IL_000f
IL_000f: ldloc.1 // V_1
IL_0010: ret
<强>代码强>
private static int Method2(bool condition)
{
if (condition)
{
return 1 + 1;
}
else
{
return 2 + 2;
}
}
<强> MSIL 强>
IL_0000: nop
IL_0001: ldarg.0 // condition
IL_0002: stloc.0 // V_0
IL_0003: ldloc.0 // V_0
IL_0004: brfalse.s IL_000b
IL_0006: nop
IL_0007: ldc.i4.2
IL_0008: stloc.1 // V_1
IL_0009: br.s IL_0010
IL_000b: nop
IL_000c: ldc.i4.4
IL_000d: stloc.1 // V_1
IL_000e: br.s IL_0010
IL_0010: ldloc.1 // V_1
IL_0011: ret