"If Not 'someCondition' Else" 逻辑
"If Not 'someCondition' Else" Logic
我有几个同事以我以前从未见过的方式实现 if-else 逻辑,这让我有些困惑。
他们写...
If <someCondition> Then
Else
Console.WriteLine("Hello, World")
...而不是
If Not <someCondition> Then
Console.WriteLine("Hello, World")
这让我开始思考
这两种方法有什么区别吗?
一种方法比另一种方法更有效吗?
让我冒险回答这个问题:
这两种方式都没有错。它是高度基于意见的。如果您的问题因此而被关闭,我也不会生气。
我认为,出现这种情况有3个主要原因
- 人们喜欢先列出积极的条件,无论是否为空
- 人们编写代码是因为他们认为会有积极的条件
- 人们后来从阳性条件中删除了代码,但
if-else
结构完好无损
两种方法都是正确的。一个比另一个没有明显的改进。
有时人们这样编码的原因是为了简单。如果你使用太多的否定,有时逻辑会变得混乱。
例如:"We don't need no education"其实就是"We do need education"
有时编码员也会得到类似的结构,为将来的逻辑修改做准备。
首先,没有性能影响,所以不要为此烦恼。其次,如果存在性能影响,那么除了最极端的情况外,在所有情况下都无需担心。所以忘掉性能,这不是性能。
那么,为什么要这样做的问题是:为了清楚地识别意图。它表明已经考虑了两个分支。我曾在极少数情况下亲自这样做过,我想 crystal 明确指出正确的做法是:什么都不做。如果此时什么都不做分支不是最重要的事情,请不要这样做。
问题:"Is there any difference between the two approaches?"
Answer: No, there is no difference.
问题:"Is one approach more efficient than the other?"
Answer: No, they are both equally efficient.
我怎么知道的?
好吧,在这种情况下,通过创建测试项目并查看编译的 IL(发布配置)很容易确定差异。
我使用 Visual Studio Community 2015 和 .NET 4.5.2 创建了一个控制台应用程序。作为反编译器,我使用了 .NET 反射器(一个免费的替代品是 ILSpy)。
VB.NET
Public Sub Test1(condition As Boolean)
If (condition) Then
Else
Console.WriteLine("condition was false.")
End If
End Sub
Public Sub Test2(condition As Boolean)
If (Not condition) Then
Console.WriteLine("condition was false.")
End If
End Sub
控制台输出:
condition was false.
condition was false.
IL
如前所述,并在下面确认,这两种方法是相同的。
.method public static void Test1(bool condition) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: brtrue.s L_000d
L_0003: ldstr "condition was false."
L_0008: call void [mscorlib]System.Console::WriteLine(string)
L_000d: ret
}
.method public static void Test2(bool condition) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: brtrue.s L_000d
L_0003: ldstr "condition was false."
L_0008: call void [mscorlib]System.Console::WriteLine(string)
L_000d: ret
}
我有几个同事以我以前从未见过的方式实现 if-else 逻辑,这让我有些困惑。
他们写...
If <someCondition> Then
Else
Console.WriteLine("Hello, World")
...而不是
If Not <someCondition> Then
Console.WriteLine("Hello, World")
这让我开始思考
这两种方法有什么区别吗? 一种方法比另一种方法更有效吗?
让我冒险回答这个问题:
这两种方式都没有错。它是高度基于意见的。如果您的问题因此而被关闭,我也不会生气。
我认为,出现这种情况有3个主要原因
- 人们喜欢先列出积极的条件,无论是否为空
- 人们编写代码是因为他们认为会有积极的条件
- 人们后来从阳性条件中删除了代码,但
if-else
结构完好无损
两种方法都是正确的。一个比另一个没有明显的改进。
有时人们这样编码的原因是为了简单。如果你使用太多的否定,有时逻辑会变得混乱。
例如:"We don't need no education"其实就是"We do need education"
有时编码员也会得到类似的结构,为将来的逻辑修改做准备。
首先,没有性能影响,所以不要为此烦恼。其次,如果存在性能影响,那么除了最极端的情况外,在所有情况下都无需担心。所以忘掉性能,这不是性能。
那么,为什么要这样做的问题是:为了清楚地识别意图。它表明已经考虑了两个分支。我曾在极少数情况下亲自这样做过,我想 crystal 明确指出正确的做法是:什么都不做。如果此时什么都不做分支不是最重要的事情,请不要这样做。
问题:"Is there any difference between the two approaches?"
Answer: No, there is no difference.
问题:"Is one approach more efficient than the other?"
Answer: No, they are both equally efficient.
我怎么知道的?
好吧,在这种情况下,通过创建测试项目并查看编译的 IL(发布配置)很容易确定差异。
我使用 Visual Studio Community 2015 和 .NET 4.5.2 创建了一个控制台应用程序。作为反编译器,我使用了 .NET 反射器(一个免费的替代品是 ILSpy)。
VB.NET
Public Sub Test1(condition As Boolean)
If (condition) Then
Else
Console.WriteLine("condition was false.")
End If
End Sub
Public Sub Test2(condition As Boolean)
If (Not condition) Then
Console.WriteLine("condition was false.")
End If
End Sub
控制台输出:
condition was false.
condition was false.
IL
如前所述,并在下面确认,这两种方法是相同的。
.method public static void Test1(bool condition) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: brtrue.s L_000d
L_0003: ldstr "condition was false."
L_0008: call void [mscorlib]System.Console::WriteLine(string)
L_000d: ret
}
.method public static void Test2(bool condition) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: brtrue.s L_000d
L_0003: ldstr "condition was false."
L_0008: call void [mscorlib]System.Console::WriteLine(string)
L_000d: ret
}