为什么String.Empty不是常量?

tra*_*vis 182 .net string constants readonly

在.Net中为什么String.Empty只读而不是常量?我只是想知道是否有人知道该决定背后的原因是什么.

Jef*_*tes 138

使用的原因static readonly是使用const非托管代码,如Microsoft在共享源公共语言基础结构2.0版本中所示.要查看的文件是sscli20\clr\src\bcl\system\string.cs.

Empty常量保存空字符串值.我们需要调用String构造函数,以便编译器不会将其标记为文字.

将其标记为文字将意味着它不会显示为我们可以从本机访问的字段.

我从CodeProject上这篇方便的文章中找到了这些信息.

  • ""看起来像是一个错误,而string.Empty显示出故意的意图 (16认同)
  • 它确实意味着必须使用""而不是string.Empty作为方法中的默认参数值.这有点烦人. (7认同)
  • @JeffYates我补充说,它不一致的事实已经很烦人了.人们会看到其余的代码,并想知道"他为什么使用""这里而不是String.Empty?".我正在认真考虑不再仅仅因为这个原因而使用`String.Empty`了. (3认同)
  • @gdoron:我的猜测是(这是一个猜测)。当将值定义为文字(常量)时,将其值插入引用的位置,而当未将其定义为文字时,将引用值的源,并在运行时检索实际值。我怀疑后者可能确保在运行时在本机和.NET之间进行适当的字符串编组-如果它是文字,则本机编译器可能需要以某种方式将文字值拉入其本机代码,这可能不是可行。不过,这全都是我的推测。 (2认同)

bru*_*nde 23

我认为这里存在很多混乱和不良反应.

首先,const字段是static成员(不是实例成员).

检查10.4节C#语言规范的常量.

尽管常量被认为是静态成员,但常量声明既不需要也不允许使用静态修饰符.

如果public const成员是静态的,则不能认为常量将创建新的Object.

鉴于此,以下代码行在创建新Object方面完全相同.

public static readonly string Empty = "";
public const string Empty = "";
Run Code Online (Sandbox Code Playgroud)

以下是Microsoft的一条说明,解释了2之间的区别:

readonly关键字与const关键字不同.const字段只能在字段声明时初始化.可以在声明或构造函数中初始化只读字段.因此,readonly字段可以具有不同的值,具体取决于所使用的构造函数.此外,虽然const字段是编译时常量,但readonly字段可用于运行时常量,...

所以我发现这里唯一合理的答案是杰夫耶茨的.

  • 重读这个,我不同意`const string`和`static readonly string`做同样的事情.Const值在链接代码中被替换,而静态只读值被引用.如果库B中使用的库A中有一个`const`,库B将用它的文字值替换对该`const`变量的所有引用; 如果该变量是"静态只读",则将引用它并在运行时确定其值. (15认同)
  • 杰夫的观点在引用库时非常重要.如果您重新编译A并重新分发它,*而不重新编译B*,B仍将使用旧值. (2认同)

Ari*_*tos 5

String.Empty read only instead of a constant?
Run Code Online (Sandbox Code Playgroud)

如果您将任何字符串设为常量,那么编译器会在您调用它的任何地方替换为实际字符串,并且您用相同的字符串填充您的代码,并且当代码运行时还需要一次又一次地从不同的内存中读取该字符串数据。

如果您将字符串保留在一个地方,因为它是String.Empty,则程序只在一个地方保留相同的字符串并读取它,或引用它 - 保持内存中的数据最少。

此外,如果您使用 String.Empty 作为 const 编译任何 dll,并且出于任何原因更改 String.Empty,则编译后的 dll 将不再相同,因为cost使内部代码实际保留字符串的副本每次通话。

例如,请参阅此代码:

public class OneName
{
    const string cConst = "constant string";
    static string cStatic = "static string";
    readonly string cReadOnly = "read only string";

    protected void Fun()
    {
        string cAddThemAll ;

        cAddThemAll = cConst;
        cAddThemAll = cStatic ;
        cAddThemAll = cReadOnly;    
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器将作为:

public class OneName
{
    // note that the const exist also here !
    private const string cConst = "constant string";
    private readonly string cReadOnly;
    private static string cStatic;

    static OneName()
    {
        cStatic = "static string";
    }

    public OneName()
    {
        this.cReadOnly = "read only string";
    }

    protected void Fun()
    {
        string cAddThemAll ;

        // look here, will replace the const string everywhere is finds it.
        cAddThemAll = "constant string";
        cAddThemAll = cStatic;
        // but the read only will only get it from "one place".
        cAddThemAll = this.cReadOnly;

    }
}
Run Code Online (Sandbox Code Playgroud)

和大会电话

        cAddThemAll = cConst;
0000003e  mov         eax,dword ptr ds:[09379C0Ch] 
00000044  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cStatic ;
00000047  mov         eax,dword ptr ds:[094E8C44h] 
0000004c  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cReadOnly;
0000004f  mov         eax,dword ptr [ebp-3Ch] 
00000052  mov         eax,dword ptr [eax+0000017Ch] 
00000058  mov         dword ptr [ebp-44h],eax 
Run Code Online (Sandbox Code Playgroud)

编辑:更正错字