.NET/BCL 源代码中“string.Empty”上方令人困惑的注释的含义?

Posted

技术标签:

【中文标题】.NET/BCL 源代码中“string.Empty”上方令人困惑的注释的含义?【英文标题】:Meaning of confusing comment above "string.Empty" in .NET/BCL source? 【发布时间】:2012-01-19 02:35:34 【问题描述】:

我试图理解为什么 string.Emptyreadonly 而不是 const。我看到了this 帖子,但我不明白微软写的关于它的评论。正如 Jon Skeet wrote 在评论中所说 “我不知道 - 老实说,这对我来说没有多大意义......”

Shared Source Common Language Infrastructure 2.0 Release。 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.Emptyreadonly而不是const


更新:Eric Lippert 现在评论了 deleted answer:

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

【问题讨论】:

也许它是那些在某一时刻有意义的 cmets 之一,但后来代码被更改,它不再有意义......不是我曾经做过那个或任何事情...... 他走开时吹口哨 "为什么不是 const" - 因为那样你就不能享受 typeof(string).GetField("Empty").SetValue(null, null);typeof(string).GetField("Empty").SetValue(null, " "); 的乐趣 - mwahahah;哇哈哈哈哈哈哈哈哈;哇哇哇哇哇哇哇哇! @MarcGravell,Eric Lippert 在需要时在哪里。 “帮我超人……” 如果 Jon Skeet 不明白,那你就完蛋了 根据评论,在过去的某个时间点,const 似乎不被视为字段。 【参考方案1】:

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

假设您有一个 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。

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

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

所以

public static readonly String Empty = ""; 

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

public static const String Empty = ""; 

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

【讨论】:

string.Empty 没有“记住”它不会被更改的好处是什么。 const 可能没问题,不是吗? 我怀疑它与编组有关:代码注释谈到能够从本机调用它,而文字不可编组。 我想了解为什么文字不可编组...文字和返回相同值的引用有什么不同? 虽然这个答案正确地描述了为什么使用readonly,但它绝不回答问题。 @MarkHurd OQ 的最后一句话是“为什么是 string.Empty readonly 而不是 const” - 所以我想,如果它“正确描述了为什么使用 readonly”,它确实回答了这个问题.不过,我可能错了!

以上是关于.NET/BCL 源代码中“string.Empty”上方令人困惑的注释的含义?的主要内容,如果未能解决你的问题,请参考以下文章

我应该使用与 .NET BCL 的名称冲突的(否则是最佳的)类名称吗?

c#窗体假死

获取转UTF8的字符串

从源代码管理 XCode 中删除 Swift 包

如何将 MySQL 代码放入源代码管理中?

Xcode 中编译源代码的目的是啥?