Warum ist String.Empty in .Net schreibgeschützt anstelle einer Konstante? Ich frage mich nur, ob jemand weiß, was die Gründe für diese Entscheidung waren.
Warum ist String.Empty in .Net schreibgeschützt anstelle einer Konstante? Ich frage mich nur, ob jemand weiß, was die Gründe für diese Entscheidung waren.
Antworten:
Der Grund, static readonly
der anstelle von verwendet wird, const
liegt in der Verwendung mit nicht verwaltetem Code, wie von Microsoft hier in der Common Language Infrastructure 2.0-Version von Shared Source angegeben . Die zu betrachtende Datei ist sscli20\clr\src\bcl\system\string.cs
.
Die leere Konstante enthält den leeren Zeichenfolgenwert. Wir müssen den String-Konstruktor aufrufen, damit der Compiler dies nicht als Literal markiert.
Wenn Sie dies als Literal markieren, wird es nicht als Feld angezeigt, auf das wir von native aus zugreifen können.
Ich habe diese Informationen aus diesem praktischen Artikel bei CodeProject gefunden .
String.Empty
nach, allein aus diesem Grund nicht mehr zu verwenden.
Ich denke, hier gibt es viel Verwirrung und schlechte Reaktionen.
Zuallererst sind const
Felder static
Mitglieder ( keine Instanzmitglieder ).
Überprüfen Sie Abschnitt 10.4 Konstanten der C # -Sprachspezifikation.
Obwohl Konstanten als statische Elemente betrachtet werden, erfordert oder erlaubt eine Konstantendeklaration keinen statischen Modifikator.
Wenn public const
Mitglieder statisch sind, kann man nicht berücksichtigen, dass eine Konstante ein neues Objekt erstellt.
Vor diesem Hintergrund machen die folgenden Codezeilen genau dasselbe in Bezug auf die Erstellung eines neuen Objekts.
public static readonly string Empty = "";
public const string Empty = "";
Hier ist ein Hinweis von Microsoft, der den Unterschied zwischen den beiden erklärt:
Das schreibgeschützte Schlüsselwort unterscheidet sich vom const-Schlüsselwort. Ein const-Feld kann nur bei der Deklaration des Feldes initialisiert werden. Ein schreibgeschütztes Feld kann entweder in der Deklaration oder in einem Konstruktor initialisiert werden. Daher können schreibgeschützte Felder je nach verwendetem Konstruktor unterschiedliche Werte haben. Während ein const-Feld eine Konstante zur Kompilierungszeit ist, kann das schreibgeschützte Feld auch für Laufzeitkonstanten verwendet werden, ...
Daher finde ich, dass die einzig plausible Antwort hier die von Jeff Yates ist.
const string
und static readonly string
mache das Gleiche. Konstantenwerte werden im verknüpften Code ersetzt, während auf statische schreibgeschützte Werte verwiesen wird. Wenn Sie eine const
in Bibliothek A haben, die von Bibliothek B verwendet wird, ersetzt Bibliothek B alle Verweise auf diese const
Variable durch ihren Literalwert. Wenn diese Variable static readonly
stattdessen wäre, würde sie zur Laufzeit referenziert und ihr Wert bestimmt.
String.Empty read only instead of a constant?
Wenn Sie eine Zeichenfolge konstant machen , wird der Compiler durch die tatsächliche Zeichenfolge ersetzt überall dort, wo Sie ihn aufrufen , und Sie füllen Ihren Code überall mit derselben Zeichenfolge. Wenn der Code ausgeführt wird, muss diese Zeichenfolge auch immer wieder aus dem anderen Speicher gelesen werden Daten.
Wenn Sie Ihre Zeichenfolge nur an einer Stelle lesen, wie es die ist String.Empty
an einer Stelle schreibgeschützt lassen, behält das Programm dieselbe Zeichenfolge nur an einer Stelle bei und liest sie oder verweist darauf - wobei die Daten im Speicher minimal bleiben.
Auch wenn Sie eine DLL mit String.Empty als const kompilieren und aus irgendeinem Grund die String.Empty-Änderung, funktioniert die kompilierte DLL nicht mehr gleich, da die cost
Code eine Kopie der Zeichenfolge enthält bei jedem Anruf.
Siehe diesen Code zum Beispiel:
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;
}
}
wird vom Compiler kommen als:
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;
}
}
und der Versammlungsaufruf
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
Bearbeiten: Tippfehler korrigiert
Diese Antwort existiert für historische Zwecke.
Ursprünglich:
weil String
es eine Klasse ist und daher keine Konstante sein kann.
Erweiterte Diskussion:
Bei der Überprüfung dieser Antwort wurden viele nützliche Dialoge herausgearbeitet, und anstatt sie zu löschen, wird dieser Inhalt direkt reproduziert:
In .NET sind (anders als in Java) Zeichenfolge und Zeichenfolge genau gleich. Und ja, Sie können String-Literal-Konstanten in .NET - DrJokepu 3. Februar 09 um 16:57 haben
Wollen Sie damit sagen, dass eine Klasse keine Konstanten haben kann? - StingyJack 3. Februar 09 um 16:58 Uhr
Ja, Objekte müssen schreibgeschützt verwendet werden. Nur Strukturen können Konstanten ausführen. Ich denke, wenn Sie
string
anstelle von verwendenString
Compilers verwenden, ändert sich die Konstante in eine für Sie schreibgeschützte. Alles damit zu tun, C-Programmierer bei Laune zu halten. - Garry Shutler 3. Februar 09 um 16:59 Uhrtvanfosson hat es nur etwas ausführlicher erklärt. "X kann keine Konstante sein, weil das enthaltende Y eine Klasse ist" war nur ein bisschen zu kontextfrei;) - Leonidas 3. Februar 09 um 17:01 Uhr
string.Empty ist eine statische Eigenschaft, die eine Instanz der String-Klasse zurückgibt, nämlich die leere Zeichenfolge, nicht die Zeichenfolgenklasse selbst. - Tvanfosson 3. Februar 09 um 17:01 Uhr
Leer ist eine schreibgeschützte Instanz (keine Eigenschaft) der String-Klasse. - Senfo 3. Februar 09 um 17:02 Uhr
Der Kopf tut weh. Ich denke immer noch, dass ich Recht habe, aber jetzt bin ich mir weniger sicher. Forschung heute Abend erforderlich! - Garry Shutler 3. Februar 09 um 17:07 Uhr
Die leere Zeichenfolge ist eine Instanz der Zeichenfolgenklasse. Leer ist ein statisches Feld (keine Eigenschaft, ich stehe korrigiert) in der String-Klasse. Grundsätzlich der Unterschied zwischen einem Zeiger und dem, worauf er zeigt. Wenn es nicht schreibgeschützt wäre, könnten wir ändern, auf welche Instanz sich das Feld Leer bezieht. - Tvanfosson 3. Februar 09 um 17:07 Uhr
Garry, du musst keine Nachforschungen anstellen. Denk darüber nach. String ist eine Klasse. Leer ist eine Instanz eines Strings. - Senfo 3. Februar 09 um 17:12 Uhr
Es gibt etwas, das ich nicht ganz verstehe: Wie um alles in der Welt kann der statische Konstruktor der String-Klasse eine Instanz der String-Klasse erstellen? Ist das nicht eine Art "Huhn oder Ei" -Szenario? - DrJokepu 3. Februar 09 um 17:12 5
Diese Antwort wäre für fast jede andere Klasse außer System.String richtig. .NET bietet eine Menge Performance-Spezialgehäuse für Zeichenfolgen. Eine davon ist, dass Sie Zeichenfolgenkonstanten haben können. Probieren Sie es einfach aus. In diesem Fall hat Jeff Yates die richtige Antwort. - Joel Mueller 3. Februar 09 um 19:25 Uhr
Wie in §7.18 beschrieben, ist ein konstanter Ausdruck ein Ausdruck, der zur Kompilierungszeit vollständig ausgewertet werden kann. Da die einzige Möglichkeit, einen Nicht-Null-Wert eines anderen Referenztyps als einer Zeichenfolge zu erstellen, darin besteht, den neuen Operator anzuwenden, und der neue Operator in einem Konstantenausdruck nicht zulässig ist, ist dies der einzig mögliche Wert für Konstanten von Referenztypen andere als Zeichenfolge ist null. Die beiden vorherigen Kommentare wurden direkt aus der C # -Sprachenspezifikation übernommen und wiederholen, was Joel Mueller erwähnte. - Senfo 4. Februar 09 um 15:05 5