在.Net中,为什么String.Empty只读而不是常量?我只是想知道是否有人知道该决定背后的原因。
在.Net中,为什么String.Empty只读而不是常量?我只是想知道是否有人知道该决定背后的原因。
Answers:
static readonly
代替const
Microsoft 的原因是由于与非托管代码一起使用,如Microsoft在“ 共享源通用语言基础结构2.0版本”中所示。要查看的文件是sscli20\clr\src\bcl\system\string.cs
。
空常量保存空字符串值。我们需要调用String构造函数,以便编译器不会将其标记为文字。
将其标记为文字将意味着它不会显示为我们可以从本地访问的字段。
我在CodeProject的这篇便利文章中找到了此信息。
String.Empty
不再仅出于这个原因不再使用它。
我认为这里有很多混乱和不良反应。
首先,const
字段是static
成员(不是实例成员)。
检查C#语言规范的10.4常量。
即使常量被认为是静态成员,常量声明也不需要也不允许使用静态修饰符。
如果public const
成员是静态的,则不能认为常量会创建一个新的Object。
鉴于此,以下代码行在创建新Object方面的作用完全相同。
public static readonly string Empty = "";
public const string Empty = "";
这是Microsoft的注释,解释了2之间的区别:
readonly关键字与const关键字不同。const字段只能在该字段的声明中初始化。只读字段可以在声明中或在构造函数中初始化。因此,只读字段可以具有不同的值,具体取决于所使用的构造函数。同样,虽然const字段是编译时常量,但readonly字段可用于运行时常量,...
因此,我发现这里唯一合理的答案是杰夫·耶茨(Jeff Yates)。
const string
并static readonly string
做同样的事情。常量值在链接的代码中被替换,而静态只读值被引用。如果您有一个const
库B使用的库A,则库B会将所有对该const
变量的引用替换为其文字值;如果static readonly
改为使用该变量,则将在运行时对其进行引用并确定其值。
String.Empty read only instead of a constant?
如果使任何字符串常量,则编译器将在调用该字符串的任何地方都替换为实际的字符串,并用相同的字符串填充代码,并且在代码运行时还需要从不同的内存中一次又一次地读取该字符串数据。
如果您将字符串仅保留在一个位置上,则String.Empty
该程序仅将一个字符串保留在一个位置上并对其进行读取或引用,以使数据在内存中的存储量最小。
另外,如果您使用String.Empty作为const编译任何dll,并且由于任何原因更改了String.Empty,则编译后的dll将不再起作用,因为cost
make内部代码实际上会保留字符串的副本在每个电话上。
例如,请参见以下代码:
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 '09 Feb 3'在16:57
您是在说一个类不能有常量吗?– StingyJack 09年2月3日在16:58
是的,对象必须使用只读。只有结构体可以做常量。我认为,当您使用
string
而不是String
编译器时,会将const更改为只读。所有与让C程序员感到高兴有关。–加里·舒特勒(Garry Shutler)'2009年2月3日在16:59tvanfosson只是稍微解释了一下。“ X不能为常数,因为包含的Y是一个类”有点上下文无关;)– Leonidas 09年2月3日在17:01
string.Empty是静态属性,它返回String类的实例,即空字符串,而不是字符串类本身。– tvanfosson 09年2月3日在17:01
空是String类的只读实例(不是属性)。– SENFO 09年2月3日在17:02
头好痛 我仍然认为我是对的,但现在我不太确定了。今晚需要研究!–加里·舒特勒(Garry Shutler)2009年2月3日在17:07
空字符串是字符串类的实例。空是String类上的静态字段(不是我所纠正的属性)。基本上,指针与其指向的东西之间的区别。如果不是只读的,我们可以更改Empty字段引用的实例。– tvanfosson 09年2月3日在17:07
加里,你不需要做任何研究。想一想。字符串是一个类。空是字符串的实例。– SENFO 09年2月3日在17:12
我还不太了解:String类的静态构造函数如何创建String类的实例?那不是某种“鸡还是蛋”的场景?– DrJokepu '09年2月3日在17:12 5
对于System.String以外的几乎所有其他类,此答案都是正确的。.NET对字符串做了很多性能上的特殊修饰,其中之一是您可以拥有字符串常量,只需尝试一下即可。在这种情况下,Jeff Yates的答案正确。–乔尔·穆勒(Joel Mueller),09年2月3日,19:25
如第7.18节所述,常量表达式是可以在编译时完全求值的表达式。由于创建除字符串以外的引用类型的非空值的唯一方法是应用new运算符,并且由于常量表达式中不允许使用新运算符,因此引用类型的常量唯一可能的值字符串以外的其他为空。前两个注释直接取自C#语言规范,并重申了Joel Mueller提到的内容。– SENFO 09年2月4日15:05 5