C#是否自动优化循环/lambda语句中的代码
本文关键字:语句 lambda 代码 循环 是否 优化 | 更新日期: 2023-09-27 18:29:24
例如,在Javascript中,强烈建议将函数调用放在循环之外以获得更好的性能:
var id = someIdType.ToString();
someList.Where(a => a.id == id) ...
C#怎么样?同样的情况还是编译器/运行时采用了内部优化/缓存?
someList.Where(a => a.id == someIdType.ToString()) ...
可能是一个noob问题,以前也被问过,但找不到参考资料。
C#代码:
List<string> list = new List<string>();
list.Where(a => a == typeof(String).ToString());
MSIL中的Lambda表达式,调试配置:
.method private hidebysig static bool '<Main>b__0'(string a) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 26 (0x1a)
.maxstack 2
.locals init ([0] bool CS$1$0000)
IL_0000: ldarg.0
IL_0001: ldtoken [mscorlib]System.String
IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000b: callvirt instance string [mscorlib]System.Object::ToString()
IL_0010: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0015: stloc.0
IL_0016: br.s IL_0018
IL_0018: ldloc.0
IL_0019: ret
} // end of method Program::'<Main>b__0'
MSIL中的Lambda表达式,发布配置:
.method private hidebysig static bool '<Main>b__0'(string a) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 22 (0x16)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldtoken [mscorlib]System.String
IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000b: callvirt instance string [mscorlib]System.Object::ToString()
IL_0010: call bool [mscorlib]System.String::op_Equality(string,
string)
IL_0015: ret
} // end of method Program::'<Main>b__0'
两个版本都调用typeof(String).ToString())
,每次迭代都会调用此lambda。没有IL级别的优化,JIT编译不会在这里添加任何内容。原因是:功能可能有副作用。
将为列表中的每个元素执行lambda。。因此,代码someIdType.ToString()
将针对每个元素执行。我不认为编译器或运行时会为您缓存它。(AFAIK someIdType
将在闭合中捕获,但不会捕获.ToString()
)
编辑:最初的问题只是关于"Do?",而不是关于"Why?",但仍然有一些评论和其他答案试图回答/证明"Why"。
鉴于人们对"为什么?"如此感兴趣,我正在编辑我的答案,以陈述我对"为什么"的看法。即,如果您查看C#规范,对于任何相关场景,该规范都会讨论capturing the variable
而不是capturing the expression
。这就是编译器的行为方式的原因。。因为它在规范中不是。为什么它不在规范中,这是C#设计团队可以回答的问题。。其余部分是推测,如果考虑feature of capturing expressions
,其部分或全部可能有价值,也可能没有价值。