String.Empty
是只读的而不是常量?我想知道背后的决策原因。static readonly
而非const
的原因是因为它与非托管代码一起使用,正如Microsoft在Shared Source Common Language Infrastructure 2.0 Release中所述。要查看的文件是sscli20\clr\src\bcl\system\string.cs
。
我从CodeProject上这篇有用的文章中找到了这些信息。Empty常量保存空字符串值。我们需要调用String构造函数,以便编译器不将其标记为文字。
将其标记为文字意味着它不会显示为一个字段,我们无法从本机访问它。
String.Empty
。 - julealgon我认为这里存在很多混乱和错误的回答。
首先,const
字段是static
成员(不是实例成员)。
请查看C#语言规范的第10.4节“常量”。
尽管常量被视为静态成员,但常量声明既不需要也不允许静态修饰符。
如果public const
成员是静态的,则不能认为常量将创建一个新对象。
鉴于此,以下代码行在创建新对象方面完全相同。
public static readonly string Empty = "";
public const string Empty = "";
这里有一份来自微软的说明,解释了两者之间的区别:
readonly关键字和const关键字不同。const字段只能在声明时初始化。readonly字段可以在声明或构造函数中初始化。因此,readonly字段可以根据使用的构造函数而有不同的值。另外,虽然const字段是编译时常量,但readonly字段可用于运行时常量...
因此,我认为这里唯一合理的答案是Jeff Yates的。
const string
和 static readonly string
具有相同的功能。const
常量在链接时被替换,而 static readonly
常量则被引用。如果在库 A 中使用了 const
,并且该常量被库 B 使用,那么库 B 将会用其字面值替换对该常量变量的所有引用;如果该变量是 static readonly
,那么它将被引用,并且其值将在运行时确定。 - Jeff YatesString.Empty read only instead of a constant?
如果您将任何字符串常量化,那么编译器将在您调用它的所有地方替换为实际字符串,并且您的代码中到处都充斥着相同的字符串。当代码运行时,还需要从不同的内存数据中再次读取该字符串。
如果您像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;
}
}
编译器将把它转换为:
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
编辑:纠正错别字
此答案仅供历史参考。
原文:
因为String
是一个类,因此不能作为常量。
扩展讨论:
在审核此答案时,进行了很多有用的对话,而不是删除它,直接复制了这些内容:
在.NET中,(与Java不同)string和String完全相同。是的,在.NET中你可以有字符串字面常量。- DrJokepu 2009年2月3日16:57