在。net中为什么是字符串。空只读而不是一个常量?我只是想知道是否有人知道这个决定背后的原因是什么。


从历史角度来看,这个答案是存在的。

原:

因为String是一个类,因此不能是常量。

扩展的讨论:

在审查这个答案的过程中,许多有用的对话框被敲出,而不是删除它,以下内容是直接复制的:

In .NET, (unlike in Java) string and String are exactly the same. And yes, you can have string literal constants in .NET – DrJokepu Feb 3 '09 at 16:57 Are you saying that a Class cannot have constants? – StingyJack Feb 3 '09 at 16:58 Yes, objects have to use readonly. Only structs can do constants. I think when you use string instead of String the compiler changes the const into a readonly for you. All to do with keeping C programmers happy. – Garry Shutler Feb 3 '09 at 16:59 tvanfosson just explained it a little bit more verbose. "X cannot be a constant, because the containing Y is a class" was just a little bit too context-free ;) – Leonidas Feb 3 '09 at 17:01 string.Empty is static property that returns an instance of the String class, namely the empty string, not the string class itself. – tvanfosson Feb 3 '09 at 17:01 Empty is a readonly instance (it's not a property) of the String class. – senfo Feb 3 '09 at 17:02 Head hurting. I still think I'm right, but now I'm less certain. Research required tonight! – Garry Shutler Feb 3 '09 at 17:07 The empty string is an instance of the string class. Empty is a static field (not a property, I stand corrected) on the String class. Basically the difference between a pointer and the thing it points to. If it weren't readonly we could change which instance the Empty field refers to. – tvanfosson Feb 3 '09 at 17:07 Garry, you don't need to do any research. Think about it. String is a class. Empty is an instance of a String. – senfo Feb 3 '09 at 17:12 There is something I don't quite get: how on earth can the static constructor of the String class create an instance of the String class ? Isn't that some sort of "chicken or the egg" scenario? – DrJokepu Feb 3 '09 at 17:12 5 This answer would be correct for nearly any other class but System.String. .NET does a lot of performance special-casing for strings, and one of them is that you CAN have string constants, just try it. In this case, Jeff Yates has the correct answer. – Joel Mueller Feb 3 '09 at 19:25 As described in §7.18, a constant-expression is an expression that can be fully evaluated at compile-time. Since the only way to create a non-null value of a reference-type other than string is to apply the new operator, and since the new operator is not permitted in a constant-expression, the only possible value for constants of reference-types other than string is null. The previous two comments were taken directly from the C# language specification and reiterate what Joel Mueller mentioned. – senfo Feb 4 '09 at 15:05 5


使用静态只读而不是const的原因是使用非托管代码,正如微软在共享源代码公共语言基础架构2.0版本中指出的那样。要查看的文件是sscli20\clr\src\bcl\system\string.cs。

Empty常量保存空值 字符串值。我们需要打电话给 字符串构造函数 编译器没有将此标记为 文字。 将此标记为字面意思将意味着 它不会显示为一个字段 我们可以从本地访问。

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


我认为这里有很多困惑和糟糕的回应。

首先,const字段是静态成员(不是实例成员)。

查看c#语言规范的10.4节常量。

即使考虑了常数 静态成员,常量声明 既不要求也不允许静态 修饰符。

如果公共const成员是静态的,就不能认为常量会创建一个新的Object。

考虑到这一点,下面几行代码在创建新对象方面做了完全相同的事情。

public static readonly string Empty = "";
public const string Empty = "";

下面是微软的一份说明,解释了两者之间的区别:

readonly关键字与 const关键字。const字段可以 只在声明时初始化 这个领域。只读字段可以是 在声明时进行初始化 或者在构造函数中。因此, 只读字段可以有不同的 值,取决于构造函数 使用。另外,const字段是 编译时常数,即read - only 字段可用于运行时 常数,…

所以我发现唯一可信的答案是杰夫·耶茨的。


String.Empty read only instead of a constant?

如果你让任何字符串为常量,那么编译器就会在你调用它的地方用实际的字符串替换,你用相同的字符串填充你的代码,当代码运行时,也需要一遍又一遍地从不同的内存数据中读取这个字符串。

如果你让你的字符串只在一个地方读,因为它是字符串。为空时,程序只在一个地方保留相同的字符串并读取它或引用它-使内存中的数据保持最小。

同样,如果你编译任何dll使用字符串。const是空的,String是空的。空更改,则编译后的dll将不再工作,因为成本使内部代码在每次调用时实际保留字符串的副本。

请看下面的代码:

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;    
    }
}

将由编译器来:

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;

    }
}

还有程序集调用

        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 

编辑:更正的错别字