Why isn't String.Empty a constant?
在.NET中,为什么string.empty是只读的而不是常量?我只是想知道是否有人知道这个决定背后的原因。
使用
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.
我从codeproject的这篇便利的文章中找到了这个信息。
我觉得这里有很多困惑和不良反应。
首先,
检查C语言规范的第10.4节常量。
Even though constants are considered
static members, a constant-declaration
neither requires nor allows a static
modifier.
如果
考虑到这一点,下面的代码行在创建新对象方面做了完全相同的事情。
1 2 | public static readonly string Empty =""; public const string Empty =""; |
以下是微软的一条注释,解释了这两种方法的区别:
The readonly keyword is different from
the const keyword. A const field can
only be initialized at the declaration
of the field. A readonly field can be
initialized either at the declaration
or in a constructor. Therefore,
readonly fields can have different
values depending on the constructor
used. Also, while a const field is a
compile-time constant, the readonly
field can be used for runtime
constants, ...
所以我发现这里唯一合理的答案是杰夫·耶茨的。
1 | String.Empty read only instead of a constant? |
如果将任何字符串设置为常量,那么编译器将替换为调用它的所有地方的实际字符串,并且在代码运行时,需要从不同的内存数据中反复读取该字符串。
如果您将字符串保持为只读,就像它是
另外,如果使用string.empty作为const编译任何dll,并且出于任何原因使用string.empty更改,则编译后的dll将不再工作,因为
请参见此代码,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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; } } |
将由编译器提供,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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; } } |
还有集会电话
1 2 3 4 5 6 7 8 9 10 | 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 |
编辑:更正的拼写错误
这个答案是出于历史目的而存在的。
原来:
因为
扩展讨论:
在审查这个答案时,我们想出了许多有用的对话,而不是删除它,而是直接复制这些内容:
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 ofString 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:59tvanfosson 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
5This 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