.net NET/BCL源代码中“string.Empty”上面的注解是否令人困惑?

gmol1639  于 2023-01-06  发布在  .NET
关注(0)|答案(2)|浏览(112)

我想弄明白为什么string.Emptyreadonly而不是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.Emptyreadonly而不是const

    • 更新日期:**

Eric Lippert评论到现在deleted answer
我在午餐时问了一位C#老前辈这个问题,他不记得具体为什么会做出这个决定,但推测这与实习有关。

ehxuflar

ehxuflar1#

重要的不是在这个类中发生了什么,而是当另一个类使用(并链接到)它时发生了什么。让我用另一个例子来解释:
假设您有一个Assembly1.dll,其中包含一个声明

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

而另一个类消费这个,例如

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包含类似于

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

它将按预期工作(链接到Assembly1.dll和Assembly2.dll之后)
现在,如果您获得了新版本的Assembly1.dll,它具有

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

如果重新编译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是框架内部的,并且不能被编组,因此不能被本机代码使用。
所以

public static readonly String Empty = "";

创建一个symbol reference(在第一次使用时通过调用String构造函数进行了重新设置),它可以封送并因此从本机使用,而

public static const String Empty = "";

会创造出一个字面量,但那不可能

wgeznvg7

wgeznvg72#

这并没有直接回答 * 为什么 *,但它提供了一些额外的上下文。String.Empty被运行时和JIT视为内在的。它的工作原理与下面的""完全相同。两者都将为您提供指向空字符串singleton的指针,并且两者的JIT代码看起来也相同。使用哪一个只是一个风格问题。此外,内存分配没有区别。

相关问题