35

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

共享源公共语言基础结构 2.0 版本。string.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 构造函数调用,此外,它被标记为文字 - “”

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


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

我在午餐时问了一位 C# 老前辈,他没有具体回忆为什么会做出这个决定,但推测这与实习有关。

4

1 回答 1

16

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

假设您有一个 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 的 SYMBOL REFERENCE,在这两种情况下都由 Assembly1.dll 的当前版本解析,因此在这两种情况下都是 0x21。

简而言之: aconst创建 a LITERAL, areadonly创建 a SYMBOL REFERENCE

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

所以

public static readonly String Empty = ""; 

创建一个symbol reference(在首次使用时通过调用 String cosntuctor 解决),可以编组一个因此从本机使用的,而

public static const String Empty = ""; 

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

于 2011-12-18T17:27:21.297 回答