C# goto语句是否影响c中的性能#
在C# goto语句是否影响c中的性能#,c#,performance,memory-management,coding-style,goto,C#,Performance,Memory Management,Coding Style,Goto,在c代码中使用GOTO语句,而不是使用loop或多个单独的用户定义函数,是否会对性能产生影响 我不确定,但是GOTO语句可能会发生内存跳转,并且会影响性能。不,不会 在不知道备选方案是什么的情况下,很难回答“它会影响绩效吗”,但我将制作一个样本: using System; public class C { public void M() { var x = 7; switch(x) // START SWITCH {
c
代码中使用GOTO
语句,而不是使用loop
或多个单独的用户定义函数,是否会对性能产生影响
我不确定,但是GOTO
语句可能会发生内存跳转,并且会影响性能。不,不会
在不知道备选方案是什么的情况下,很难回答“它会影响绩效吗”,但我将制作一个样本:
using System;
public class C {
public void M() {
var x = 7;
switch(x) // START SWITCH
{
case 1:
Console.WriteLine("Hello");
break;
case 2:
Console.WriteLine("World");
break;
default:
Console.WriteLine("Uh...");
break;
}
// END SWITCH
// START GOTO
if (x == 1)
{
goto Hello;
}
else if (x == 2)
{
goto World;
}
Console.WriteLine("Uh...");
goto End;
Hello:
Console.WriteLine("Hello");
goto End;
World:
Console.WriteLine("World");
End:
// END GOTO
Console.WriteLine("Done");
}
}
在发布模式下使用C#编译此文件(使用sharplab.io default 2.9.0)会产生以下IL(即Java语言的字节码):
.class私有自动ansi“”
{
}//下课
.class公共自动ansi BEFOREFILDInit C
扩展[mscorlib]System.Object
{
//方法
.方法公共隐藏
实例void M()cil托管
{
//方法从RVA 0x2050开始
//代码大小99(0x63)
.maxstack 2
.init(
[0]int32
)
IL_0000:ldc.i4.7
IL_0001:stloc.0
//起动开关
IL_0002:ldloc.0
IL_0003:ldc.i4.1
IL_0004:beq.s IL_000c
IL_0006:ldloc.0
IL_0007:ldc.i4.2
IL_0008:beq.s IL_0018
ILU 000a:br.s ILU 0024
IL_000c:ldstr“你好”
IL_0011:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_0016:br.s IL_002e
IL_0018:ldstr“世界”
IL_001d:调用void[mscorlib]System.Console::WriteLine(字符串)
ILU 0022:br.s ILU 002e
IL_0024:ldstr“呃…”
IL_0029:调用void[mscorlib]System.Console::WriteLine(字符串)
//终端开关
//开始转到
IL_002e:ldloc.0
IL_002f:ldc.i4.1
IL_0030:beq.s IL_0042
IL_0032:ldloc.0
IL_0033:ldc.i4.2
IL_0034:beq.s IL_004e
IL_0036:ldstr“呃…”
IL_003b:调用void[mscorlib]System.Console::WriteLine(字符串)
ILU 0040:br.s ILU 0058
ILU 0042:ldstr“你好”
IL_0047:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_004c:br.s IL_0058
ILU 004e:ldstr“世界”
IL_0053:调用void[mscorlib]System.Console::WriteLine(字符串)
//结束后藤
IL_0058:ldstr“完成”
IL_005d:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_0062:ret
}//方法C::M的结尾
.method公共隐藏显示特殊名称rtspecialname
实例void.ctor()cil托管
{
//方法从RVA 0x20bf开始
//代码大小7(0x7)
.maxstack 8
IL_0000:ldarg.0
IL_0001:调用实例void[mscorlib]System.Object::.ctor()
IL_0006:ret
}//方法C的结尾::.ctor
}//C类结束
切换表单有3个beq
和1个br.s
,转到表单有2个beq
和2个br.s
,不同的是它们是相同的。br.s
的成本大概小于或等于beq
的成本,因此转到方法的成本不大于切换方法的成本
最后,使用goto是个坏主意。如果您想争论这个事实,请在另一个问题上这样做:性能影响与否,它会破坏您的可维护性。永远不要使用GOTO
s,除非你陷入了一个没有任何选择的真正特定的小问题。当你尝试使用GOTO
时,你发现了什么性能差异?你确实试过了,对吗?我不像Pierre Luc那样相信,简单地使用goto
意味着破坏您的可维护性。当然,这是一种强制性的方法来编写fall-throughcase
块。另一方面,对于流量控制,一个goto
确实留下了很多需要改进的地方,而且几乎总是可以避免的。所以你也可以;即使可维护性没有被一个goto
破坏,它肯定会有点污点。:)@PeterDuniho方法用于增强可读性。经典的for
和而循环易于识别和阅读GOTO
s只会制造一个巨大的混乱,完全违背了OOP的基本原则、SRP,并且会在阻止任何可测试性的同时使圈复杂度急剧上升。我敢说,你可以尝试在完全相同的时间内理解一个带有gotos的5k行方法,而不是一个干净的结构化OOP架构。老实说,如果你想对循环和方法等东西进行微优化(当然是毫无益处的),那就直接进行组装吧。@Pierre Luccinoult:谁说了五千行的方法?让我休息一下……仅仅因为goto
语句可能是代码的一部分,否则也很糟糕,没有理由相信代码中的一个goto
语句会毁掉代码。@Peter他谈到使用goto而不是方法。如果程序生成5k行,这意味着您有一个5k行的单一方法。我们这里说的不是一个goto(即使已经够危险了),而是用em替换所有的循环。
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit C
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig
instance void M () cil managed
{
// Method begins at RVA 0x2050
// Code size 99 (0x63)
.maxstack 2
.locals init (
[0] int32
)
IL_0000: ldc.i4.7
IL_0001: stloc.0
// START SWITCH
IL_0002: ldloc.0
IL_0003: ldc.i4.1
IL_0004: beq.s IL_000c
IL_0006: ldloc.0
IL_0007: ldc.i4.2
IL_0008: beq.s IL_0018
IL_000a: br.s IL_0024
IL_000c: ldstr "Hello"
IL_0011: call void [mscorlib]System.Console::WriteLine(string)
IL_0016: br.s IL_002e
IL_0018: ldstr "World"
IL_001d: call void [mscorlib]System.Console::WriteLine(string)
IL_0022: br.s IL_002e
IL_0024: ldstr "Uh..."
IL_0029: call void [mscorlib]System.Console::WriteLine(string)
// END SWITCH
// START GOTO
IL_002e: ldloc.0
IL_002f: ldc.i4.1
IL_0030: beq.s IL_0042
IL_0032: ldloc.0
IL_0033: ldc.i4.2
IL_0034: beq.s IL_004e
IL_0036: ldstr "Uh..."
IL_003b: call void [mscorlib]System.Console::WriteLine(string)
IL_0040: br.s IL_0058
IL_0042: ldstr "Hello"
IL_0047: call void [mscorlib]System.Console::WriteLine(string)
IL_004c: br.s IL_0058
IL_004e: ldstr "World"
IL_0053: call void [mscorlib]System.Console::WriteLine(string)
// END GOTO
IL_0058: ldstr "Done"
IL_005d: call void [mscorlib]System.Console::WriteLine(string)
IL_0062: ret
} // end of method C::M
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20bf
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method C::.ctor
} // end of class C