最近在编程时遇到这个问题,我一直在想这个。以下是两个合法和编译的片段。具体来说,我的问题是这个..在第二种情况下,括号是否使程序变慢?为什么这也允许?
第一种情况:
if (statement)
{
// do something
}
第二种情况:
{
if (statement)
{
// do something
}
}
另外如果我有类似下面的代码的话。运行时是否与调用函数X相同而没有任何大括号。
{
{
{
// call function X
}
}
}
答案 0 :(得分:12)
大多数当时它没有任何区别 - 你绝对应该编写可读性的代码。
然而,花括号可以以惊人的方式对性能产生影响,尽管这很不寻常。请考虑以下代码:
MySqlDateTime mdt = (MySqlDateTime) dataRead["user_date"]
Console.WriteLine(mdt.ToString("M/d/yyyy HH:mm:ss"));
using System;
using System.Collections.Generic;
class Test
{
static void FewerCurlies()
{
List<Action> actions = new List<Action>();
for (int i = 0; i < 100; i++)
{
int x;
if (i % 3 == 0)
{
actions.Add(() => x = 10);
}
int y;
if (i % 3 == 1)
{
actions.Add(() => y = 10);
}
}
}
static void MoreCurlies()
{
List<Action> actions = new List<Action>();
for (int i = 0; i < 100; i++)
{
{
int x;
if (i % 3 == 0)
{
actions.Add(() => x = 10);
}
}
{
int y;
if (i % 3 == 1)
{
actions.Add(() => y = 10);
}
}
}
}
}
中的额外括号看起来多余,对吗?不完全......生成的代码看起来更像是这样:
MoreCurlies
这里的区别是:
using System;
using System.Collections.Generic;
class Test
{
static void FewerCurlies()
{
List<Action> actions = new List<Action>();
for (int i = 0; i < 100; i++)
{
FewerCurliesCapture capture = new FewerCurliesCapture();
if (i % 3 == 0)
{
actions.Add(capture.Method1);
}
if (i % 3 == 1)
{
actions.Add(capture.Method2);
}
}
}
static void MoreCurlies()
{
List<Action> actions = new List<Action>();
for (int i = 0; i < 100; i++)
{
{
MoreCurliesCapture1 capture = new MoreCurliesCapture1();
if (i % 3 == 0)
{
actions.Add(capture.Method);
}
}
{
MoreCurliesCapture1 capture = new MoreCurliesCapture2();
if (i % 3 == 1)
{
actions.Add(capture.Method);
}
}
}
}
private class FewerCurliesCapture
{
public int x;
public int y;
public void Method1()
{
x = 10;
}
public void Method2()
{
y = 10;
}
}
private class MoreCurliesCapture1
{
public int x;
public void Method()
{
x = 10;
}
}
private class MoreCurliesCapture2
{
public int y;
public void Method()
{
y = 10;
}
}
}
的循环的每次迭代中创建捕获类的实例,即使它未被使用FewerCurlies
中使用的捕获类的每个实例都包含两个变量,即使每个委托实际上只使用其中一个,而在FewerCurlies
中每个捕获类只捕获一个变量这有点特定于实现,但它表明多余的curlies 可以产生影响。
答案 1 :(得分:4)
与此类问题一样,答案在于它产生的IL。对于以下代码示例:
catch
我们最终得到以下编译的IL:
public int X()
{
{
{
{
return 0;
}
}
}
}
public int Y()
{
return 0;
}
他们是完全相同的。所以不,它对性能没有影响。 .method public hidebysig instance int32 X() cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ret
} // end of method SomeType::X
.method public hidebysig instance int32 Y() cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ret
} // end of method SomeType::Y
阅读起来很糟糕,但这是另一个问题。
<强>更新强>
X
会影响变量的范围,因此可能会产生影响。再次,让我们检查一下:
{}
再一次,IL产生的是相同的:
public int X()
{
var i = 1;
{
{
i++;
{
return i;
}
}
}
}
public int Y()
{
var i = 1;
i++;
return i;
}
但是如果在闭包中捕获变量,它确实会影响事物。在以下情况中,// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.1
IL_0004: add
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ret
会产生更多IL,这会对性能产生影响:
X
答案 2 :(得分:3)
简短回答是“不,他们不会降低表现”。
编译器需要使用大括号来确定变量的范围,并知道当前语句组的结束位置。一旦编译器完成处理,带有和不带有不必要花括号的代码将产生相同的输出。
请注意,这与编译代码的性能有关,而与编译器本身的性能无关。编译器将花费额外的时间来编译代码,因为输入的原始大小更大。但是,为了使这个额外的时间变得可测量,不必要的括号的数量需要相当极端。
答案 3 :(得分:2)
与C ++不同,C ++中可能需要编译器在变量进入或超出范围时生成代码,C#中的大多数变量都被有效地提升到封闭的函数级范围。代码:
void foo()
{
{
int i;
... stuff using i as int
}
{
char i;
... stuff using i as char
}
}
将有效地变成:
void foo()
{
int i__1;
char i__2;
... stuff using i__1 as int
... stuff using i__2 as char
}
使用第一个支撑部分的代码,使用第一个变量i__1
,无论它在哪里使用i
,第二个使用i__2
编码。在某些情况下,在多个作用域块中声明具有相同名称和用途的变量可能会产生比在外部作用域中声明具有该共同目的的一个变量更低效的代码,但它很少会产生有意义的影响。在大多数情况下,即时编译器将能够确定代码中的多个变量可以安全地映射到同一存储位置,甚至可以在那些可以满足一些额外变量所需的存储的位置。不太可能影响表现。
答案 4 :(得分:1)
没有花括号不会降低性能。
它有助于深入了解代码并提供良好的代码格式。但是一些花括号是强制性的,如函数开始/结束,循环开始/结束,条件开始/结束,这个条件也有助于理解变量scrop。
答案 5 :(得分:0)
使用不必要的花括号,假设您没有嵌套变量,只会在将代码转换为字节代码或机器代码时向标签表添加标签。所以更糟糕的是构建时间会变慢。如果嵌套中有变量,如果它们是没有破坏代码的基元但是如果你在嵌套大括号中创建了对象,那么你仍然不应该有问题,那么需要更好地理解GC,但我强烈怀疑任何明显的差异都会出现。在所有情况下,因为编译器通过在构建项目时将引用存储在查找表中来执行额外的工作,所以在构建项目时会有一个(尽管可能不明显的)延迟。
答案 6 :(得分:-1)
它不会导致任何性能下降,但使用花括号肯定会增加代码的可读性。 在真正的单词场景中,当您进行同行代码审查或结对编程时,您编写的内容将非常清晰和可读。
浏览以下链接