C# If and return有效还是If and else有效/推荐?
有人能告诉我以下两个片段中哪一个是有效的/推荐的,为什么C# If and return有效还是If and else有效/推荐?,c#,C#,有人能告诉我以下两个片段中哪一个是有效的/推荐的,为什么 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(c
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
}
}
以下问题的答案并没有提及我的问题在效率或推荐做法方面的任何内容,问题似乎只是在问什么是正确的
就执行速度而言,可能没有什么区别值得考虑 就可读性而言,我建议你把这个问题放到另一个层次,看看它会带来什么。这两个示例遵循您的两种模式,但针对一个不太重要的问题。哪个更容易阅读
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();
}
第一个模式将使用,而第二个模式将使用。箭头被认为是反模式
当您展平箭头以使用保护时,您可以减少、减少代码长度,减少滚动查看完整代码块的需要,并减少理解平均代码行含义所需的心理操作次数
第二种方法在客观上几乎在所有方面都更好,除了非常琐碎的逻辑之外,在这种逻辑中,
其他
可以更清楚地传达您试图实现的目标。性能上绝对没有差异。在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
{
}
}
在优化应用程序时,首先看看真正的瓶颈是什么。找出导致最长延迟的原因,并开始对此进行优化。您当前正在尝试的操作称为过早优化。正因为如此,您的代码变得可读性较差,可能速度较慢,并且更容易出现错误。如果您患有MSIL OCD(强迫症),您可以通过不使用其他
来保存自己的操作码。Nop
如果操作码已修补,则填充空间。没有任何有意义的操作是必要的
尽管可以消耗处理周期,但仍执行
代码
private static int Method1(bool condition)
{
if (condition)
{
return 1+1;
}
return 2 + 2;
}
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_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
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
代码
private static int Method1(bool condition)
{
if (condition)
{
return 1+1;
}
return 2 + 2;
}
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_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
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
关于效率,这根本没有区别。因此,请使用使代码更具可读性的选项。在像您这样的简单例子中,
if
/else
的对称性很好。但是,例如,如果您有几个“guard”测试要在函数顶部进行检查,如果其中任何一个测试失败,那么最好给每个测试一个if
/return
,以避免不必要的缩进。这是您的应用程序的瓶颈吗?另请参见:自然地安排代码以避免标签堆积如山通常有利于可读性。不过,这在性能上没有什么区别。在描述它时有困难,但欢迎您添加另一个答案并提供一个示例。我只是想,如果我们删除return
语句,将它们全部设置为,否则如果语句,并更换!c
如果(c)
,只需检查。类似于:if(!a)x();如果(!b)y();如果(c)d()代码>不太重要,绝对不值得一个新答案。:)