我想弄明白为什么string.Empty
是readonly
而不是const
。我看了this的帖子,但我不明白微软写的评论。正如Jon Skeet wrote在评论中所说 "我不知道--老实说,这对我来说没有多大意义......"
字符串. cs位于sscli20\clr\src\bcl\system\string.cs中
// The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field which we can access
//from native.
public static readonly String Empty = "";
我在这里看不到任何String构造函数调用,而且,它被标记为literal-""
有人能用纯文本解释一下吗?评论是什么意思?为什么是string.Empty
readonly
而不是const
?
- 更新日期:**
Eric Lippert评论到现在deleted answer:
我在午餐时问了一位C#老前辈这个问题,他不记得具体为什么会做出这个决定,但推测这与实习有关。
2条答案
按热度按时间ehxuflar1#
重要的不是在这个类中发生了什么,而是当另一个类使用(并链接到)它时发生了什么。让我用另一个例子来解释:
假设您有一个Assembly1.dll,其中包含一个声明
而另一个类消费这个,例如
您将类编译到Assembly2.dll中,并将其链接到Assembly1.dll,正如预期的那样,您的方法将在参数无效时返回0x10,在其他错误时返回0x20,在成功时返回0x00。
特别是,如果您创建的Assembly3.exe包含类似于
它将按预期工作(链接到Assembly1.dll和Assembly2.dll之后)
现在,如果您获得了新版本的Assembly1.dll,它具有
如果重新编译Assembly3.exe并将最后一个片段链接到新的Assembly1.dll和未更改的Assembly2.dll,则它将按预期停止工作:
将无法正确调用bar():Assembly2.dll会记住LITERAL 0x20,它与Assembly3.exe从Assembly1.dll中读取的文本0x21不同
baz()将被正确调用:Assembly2.dll和Assembly3.exe都引用名为SOME_OTHER_ERROR_CODE的符号引用,在这两种情况下,当前版本的Assembly1.dll都已解析该符号引用,因此在这两种情况下,该符号引用都是0x21。
简而言之:一个
const
创建一个LITERAL
,一个readonly
创建一个SYMBOL REFERENCE
。LITERALS
是框架内部的,并且不能被编组,因此不能被本机代码使用。所以
创建一个
symbol reference
(在第一次使用时通过调用String构造函数进行了重新设置),它可以封送并因此从本机使用,而会创造出一个字面量,但那不可能
wgeznvg72#
这并没有直接回答 * 为什么 *,但它提供了一些额外的上下文。
String.Empty
被运行时和JIT视为内在的。它的工作原理与下面的""
完全相同。两者都将为您提供指向空字符串singleton的指针,并且两者的JIT代码看起来也相同。使用哪一个只是一个风格问题。此外,内存分配没有区别。