关于c#:在.NET / BCL源代码中混淆注释“string.Empty”的含义?

Meaning of confusing comment above “string.Empty” in .NET/BCL source?

我试图理解为什么string.Emptyreadonly,而不是const。我看过这篇文章,但我不理解微软写的关于它的评论。乔恩·斯基特在一篇评论中写道:"我不知道——老实说,这对我来说没什么意义……"

共享源公共语言基础结构2.0版本。string.cs位于sscli20clrsrcclsystemstring.cs中

1
2
3
4
5
// 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 ="";

我在这里看不到任何字符串构造函数调用,而且它被标记为literal-

有人能用纯文本向我解释一下吗?这个评论是什么意思?为什么string.Emptyreadonly而不是const呢?

更新:埃里克·利珀特现在评论了一个删除的答案:

I asked one of the C# old-timers over lunch about this and he did not recall specifically why this decision was made, but conjectured that it had something to do with interning.


重要的部分不是这个类中发生的事情,而是当另一个类使用(和链接到)它时发生的事情。让我用另一个例子来解释:

假设您有一个assembly1.dll,其中包含一个类声明

1
2
public static const int SOME_ERROR_CODE=0x10;
public static readonly int SOME_OTHER_ERROR_CODE=0x20;

而另一类人则是这样消费的。

1
2
3
4
5
6
public int TryFoo() {
    try {foo();}
    catch (InvalidParameterException) {return SOME_ERROR_CODE;}
    catch (Exception) { return SOME_OTHER_ERROR_CODE;}
    return 0x00;
}

将类编译为assembly2.dll并将其与assembly1.dll链接,如预期的那样,方法将在无效参数上返回0x10,在其他错误上返回0x20,在成功时返回0x00。

尤其是,如果创建的assembly3.exe包含

1
2
3
int errorcode=TryFoo();
if (errorcode==SOME_ERROR_CODE) bar();
else if (errorcode==SOME_OTHER_ERROR_CODE) baz();

它将按预期工作(在链接到assembly1.dll和assembly2.dll之后)

现在,如果获得assembly1.dll的新版本,则

1
2
public const int SOME_ERROR_CODE=0x11;
public readonly int SOME_OTHER_ERROR_CODE=0x21;

如果重新编译assembly3.exe并将最后一个片段链接到新assembly1.dll和未更改的assembly2.dll,则它将按预期停止工作:

无法正确调用bar():assembly2.dll记住文字0x20,它与assembly3.exe从assembly1.dll中读取的文字0x21不同。

baz()将被正确调用:assembly2.dll和assembly3.exe都引用了名为某些其他_错误_代码的符号引用,这两种情况下都由当前版本的assembly1.dll解决,因此在这两种情况下都是0x21。

简而言之:const创建LITERALreadonly创建SYMBOL REFERENCE

LITERALS是框架内部的,不能被编组,因此被本地代码使用。

所以

1
public static readonly String Empty ="";

创建一个SYMBOL REFERENCE(在第一次使用时由对字符串cosntructor的调用重新解析),它可以从本机对这样使用的进行编组,而

1
public static const String Empty ="";

会创建一个文本,但不能。