上面"string.Empty"在 .NET/BCL 源中混淆注释的含义?



我试图理解为什么string.Emptyreadonly而不是const。我看到了这篇文章,但是我不明白微软写的评论。正如Jon Skeet在评论中写道:"我不知道——老实说,这对我来说没有多大意义……"

共享源公共语言基础设施2.0发布。字符串。cs位于sscli20clrsrcbclsystem 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构造函数调用,而且,它被标记为文字- "

有人可以用明文解释我,评论是什么意思,为什么是string.Empty readonly而不是const ?


更新:
Eric Lippert现在评论了一个被删除的答案:

我在午餐时问了一位c#老手,他没有具体回忆起为什么要做出这个决定,但他猜测这与实习有关。

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

假设您有一个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 = ""; 

将创建一个文字,而不能。

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

最新更新