如何在不进行系统调用的情况下获得恒定的字符串长度?

Har*_*rry 3 c# optimization cil

示例代码:

const string UtcTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffZ";
public byte[] UtcTimeAscii => Encoding.ASCII.GetBytes(DateTime.UtcNow.ToString(UtcTimeFormat));
Run Code Online (Sandbox Code Playgroud)

这是我得到的属性 IL Length:(使用MicroscopeVS 添加) 在此输入图像描述

现在:为什么有一个系统调用而不是简单的24?这是一个常量字符串。有没有办法告诉编译器它是提前知道的?

我知道,我可以定义24const int,但这是不对的,因为实际字符串与其长度之间没有直接绑定。当然我可以调用Length(),但我只是好奇,也许有特殊的语法来使用这种优化?

我还将配置从 切换DebugRelease但系统调用仍然存在。

har*_*old 8

如果要完成该优化,则不会由 C# 编译器完成,而是由 JIT 编译器在运行时(好吧,就在运行之前)完成。IL 通常并不表明正在发生哪些优化,并且永远无法证明不存在给定的优化。

那么让我们看看实际运行的结果机器代码。如果关闭“禁用模块加载优化”(否则您会看到故意未优化的机器代码),您可以在调试器中执行此操作,或者您可以使用 Sharplab.io:像这样

C.M()
    L0000: mov eax, 0x18
    L0005: ret
Run Code Online (Sandbox Code Playgroud)

结果很明显:获取常量字符串的长度被优化为常量长度,不涉及调用甚至加载。顺便说一句,在任何情况下它都不是系统调用,它可能是对子例程的正常调用。