为什么作为引用类型的string可以是非空const,而其他引用类型的const必须为空?

本文关键字:引用类型 const 其他 是非 string 为什么 | 更新日期: 2023-09-27 18:12:30

据我所知,string是引用类型。const只有配以null才能与reference型配合使用。我的问题是

为什么string是一个引用类型可以被分配一个字面值字符串(或非空)?

为什么作为引用类型的string可以是非空const,而其他引用类型的const必须为空?

取自const文档:

常数表达式是可以在编译时完全求值的表达式。因此,引用类型的常量唯一可能的值是字符串和空引用。

换句话说,它是一个异常。如果没有字符串常量这类东西,生活将会困难得多。

您还可以记住,它不是所有字符串,例如,您不能用代码const string test = new string('t', 7);编译,尽管您可以用static string test = new string('t', 7);编译。另一方面,虽然可以将字符串常量定义为字符串字面值(test = "value";),但不能使用字面值(Form f = ???)定义任何其他引用类型。

这是c#语言中的一个特殊规则,也是CLR的一个特性。编译器知道如何将字符串嵌入到汇编元数据中。

ECMA-334 c#规范有以下说明(强调我的):

如§14.16所述,常量表达式是可以在编译时完全求值的表达式。因为创建非字符串引用类型的非空值的唯一方法是应用由于常量表达式中不允许使用New操作符,因此唯一可能的值是对于除string以外的引用类型的常量为null。

根据MSDN:

常量可以是数字、布尔值、字符串或空引用。

每个程序集包含一个字节序列,该字节序列包含程序集中定义的所有字符串,当类型加载时,系统将使用该序列中的字节创建一个新的字符串对象列表。在程序集中声明的每个字符串字面量都被分配一个索引,并且加载字符串字面量的指令从加载该程序集中创建的字符串对象表中读取字符串对象。

这种行为对于任何不包含任何嵌套类类型字段的类类型都是可能的,但通常只对不可变类类型有用。由于没有通用的方法来区分不可变的类类型,特别是考虑到程序集可能会加载像Tuple<int, int>这样的类型的"不寻常"定义的可能性,这种行为仅限于满足该标准的一个类类型,而不能做其他事情:System.String .