c# - 在哪里可以找到MSIL字符串常量中的转义字符列表?

标签 c# .net cil

我已经编写了一个程序(使用C#),该程序读取和操作从C#程序生成的MSIL程序。我错误地认为MSIL字符串常量的语法规则与C#相同,但是随后遇到以下情况:

此C#语句

string s = "Do you wish to send anyway?";

被编译为(除其他MSIL语句外)
IL_0128:  ldstr      "Do you wish to send anyway\?"

我没想到用来逃避问号的反斜杠。现在,我可以在处理过程中清楚地考虑到反斜杠了,但是出于好奇,我想知道当C#编译器将C#常量字符串转换为MSIL常量字符串时,是否存在某个字符转义的列表。

谢谢。

最佳答案

更新

基于使用C#编译器+ ildasm.exe进行的实验:也许没有转义字符列表的原因是因为转义字符太少:恰好是6。

从ildasm生成的IL,从Visual Studio 2010编译的C#程序中获取:

  • IL严格来说是 ASCII
  • 逃脱了三个传统的空白字符
  • \t:0x09:(tab)
  • \n:0x0A :(新行)
  • \r:0x0D :(回车)
  • 转义了三个标点符号:
  • \":0x22 :(双引号)
  • \?:0x3F :(问号)
  • \\:0x5C :(反斜杠)
  • 文字字符串0x20-0x7E中仅完整包含以下字符(不包括三个标点符号)
  • 所有其他字符(包括0x20以下的ASCII控制字符以及从0x7F开始的所有字符)都转换为字节数组。或者更确切地说,包含除以上92个立即数和6个转义字符之外的任何字符的任何字符串都将转换为字节数组,其中字节是UTF-16字符串的 little-endian 字节。

  • 示例1:0x7E以上的ASCII:简单的重音é(U + 00E9)

    C#:成为"é""\u00E9"(E9字节排在最前面)
    ldstr      bytearray (E9 00 )
    

    示例2:UTF-16:求和符号∑(U + 2211)

    C#:成为"∑""\u2211"(11字节排在最前面)
    ldstr      bytearray (11 22 )
    

    示例3:UTF-32:Double-struck mathematical(U + 1D538)

    C#:"𝔸"或UTF-16代理对"\uD835\uDD38"变为(char内的字节反转,但总体顺序为双字节char)
    ldstr      bytearray (35 D8 38 DD )
    

    示例4:字节数组转换适用于包含非Ascii字符的整个字符串

    C#:"In the last decade, the German word \"über\" has come to be used frequently in colloquial English."变为
    ldstr      bytearray (49 00 6E 00 20 00 74 00 68 00 65 00 20 00 6C 00  
                          61 00 73 00 74 00 20 00 64 00 65 00 63 00 61 00  
                          64 00 65 00 2C 00 20 00 74 00 68 00 65 00 20 00  
                          47 00 65 00 72 00 6D 00 61 00 6E 00 20 00 77 00  
                          6F 00 72 00 64 00 20 00 22 00 FC 00 62 00 65 00  
                          72 00 22 00 20 00 68 00 61 00 73 00 20 00 63 00  
                          6F 00 6D 00 65 00 20 00 74 00 6F 00 20 00 62 00  
                          65 00 20 00 75 00 73 00 65 00 64 00 20 00 66 00  
                          72 00 65 00 71 00 75 00 65 00 6E 00 74 00 6C 00  
                          79 00 20 00 69 00 6E 00 20 00 63 00 6F 00 6C 00  
                          6C 00 6F 00 71 00 75 00 69 00 61 00 6C 00 20 00  
                          45 00 6E 00 67 00 6C 00 69 00 73 00 68 00 2E 00 )
    

    直接地,“您不能”(找到MSIL字符串转义符列表),但是这里有一些有用的提示...

    ECMA-335包含CIL的严格定义,未指定QSTRING文字中必须转义哪些字符,只是未使用反斜线\字符进行转义。最重要的注意事项是:
  • Unicode文字表示为八进制而不是十六进制(即\042而不是\u0022)。
  • 可以使用\字符将字符串分布在多行中-见下文

  • 唯一明确提到的转义符是\t标签,换行\n八进制数字转义符。由于C#没有八进制文字,因此这对您来说有点烦人-您必须自己进行提取和转换,例如使用Convert.ToInt32([string], 8)方法。

    除转义的选择之外,还对规范中描述的“假设的IL汇编器”是“特定于实现的”。因此,您的问题正确地询问了MSIL的规则,这是Microsoft严格执行的CIL。据我所知,MS尚未记录他们对转义的选择。至少问一下Mono的人可能会有用。除此之外,可能还需要自己生成列表-创建一个为每个字符\u0000声明一个字符串文字的程序-无论如何,然后查看编译后的ldstr语句是什么。如果首先解决问题,我将确保发布结果。

    其他说明:

    要正确解析* IL字符串文字(称为QSTRINGS或SQSTRINGS),您将不仅要考虑字符转义。以代码中的字符串连接为例(这是分区II::5.2的逐字记录):

    The "+" operator can be used to concatenate string literals. This way, a long string can be broken across multiple lines by using "+" and a new string on each line. An alternative is to use "\" as the last character in a line, in which case, that character and the line break following it are not entered into the generated string. Any white space characters (space, line-feed, carriage-return, and tab) between the "\" and the first non-white space character on the next line are ignored. [Note: To include a double quote character in a QSTRING, use an octal escape sequence. end note]

    Example: The following result in strings that are equivalent to "Hello World from CIL!":


    ldstr "Hello " + "World " + "from CIL!"
    
    ldstr "Hello World\ 
           \040from CIL!"
    

    关于c# - 在哪里可以找到MSIL字符串常量中的转义字符列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9113440/

    相关文章:

    .net - 为什么 .NET 代码编译为 MSIL?

    c# - 为什么不能在泛型中要求运算符重载

    c# - 多个线程等待一个事件?

    c# - 如何从 SOAP 消息中检索集合

    C# - 在按下按钮之前使 UI 像无限循环一样运行

    c# - 如何启动 Windows 窗体应用程序?

    c# - 从临时 ASP.NET 文件中清除冲突的类文件

    c# - SQLBulkCopy 不复制主键

    c# - 如何使用正则表达式从字符串中获取 ID

    c# - 了解 C# 编译器如何处理链接 linq 方法