Was ist der Unterschied zwischen String und String in C #?

6507

Beispiel ( beachten Sie den Fall ):

string s = "Hello world!";
String s = "Hello world!";

Was sind die Richtlinien für die Verwendung von jedem? Und was sind die Unterschiede?

Peter O.
quelle
72
@ORMapper, aber die Tatsache bleibt, dass stringes sich um ein lexikalisches Konstrukt der C # -Grammatik handelt, während System.Stringes sich nur um einen Typ handelt. Unabhängig von einem expliziten Unterschied, der in einer Spezifikation erwähnt wird, gibt es immer noch diesen impliziten Unterschied, der mit einer gewissen Mehrdeutigkeit einhergehen könnte. Die Sprache selbst muss so unterstützt werden string, dass die Implementierung nicht (ganz) verpflichtet ist, für eine bestimmte Klasse in der BCL zu berücksichtigen.
Kirk Woll
106
@KirkWoll: Nach der Sprachspezifikation, die Sprache selbst müssen prüfen stringgenau die gleiche wie die BCL - Typ sein System.String, nichts anderes. Das ist überhaupt nicht mehrdeutig. Natürlich können Sie Ihren eigenen Compiler mithilfe der C # -Grammatik implementieren und alle so gefundenen Token für etwas Beliebiges verwenden, das nichts mit dem zu tun hat, was in der C # -Sprachenspezifikation definiert ist. Die resultierende Sprache wäre jedoch nur C # -ähnlich, sie könnte nicht als C # betrachtet werden.
ODER Mapper
88
Sie können stringohne using-Direktive für System verwenden. Das kann man nicht machen String.
Wilsu
14
Für jemanden aus Algol und Fortran zeigt diese Diskussion, dass etwas nicht stimmt string. Es wird benötigt, um abzukürzen System.String, aber als Alias ​​scheint es ziemlich ähnlich, aber nicht genau dasselbe. Nach mehreren Jahren der C #, ich würde aber sagen, es sicher ist , einfach zu bedienen stringund string.Format()nicht zu befürchten System.String.
Roland
8
@Sangeeta Was sagst du? Die System.StringKlasse ist immer noch da und das stringSchlüsselwort ist immer noch ein Alias ​​dafür. Genau wie System.Int32und int. Sie sind buchstäblich dasselbe.
Craig

Antworten:

6104

stringist ein Alias ​​in C # für System.String.
Technisch gesehen gibt es also keinen Unterschied. Es ist wie int gegen System.Int32 .

In stringBezug auf Richtlinien wird generell empfohlen, jedes Mal zu verwenden, wenn Sie sich auf ein Objekt beziehen.

z.B

string place = "world";

Ebenso denke ich, dass es allgemein empfohlen wird, zu verwenden, Stringwenn Sie sich speziell auf die Klasse beziehen müssen.

z.B

string greet = String.Format("Hello {0}!", place);

Dies ist der Stil, den Microsoft in seinen Beispielen verwendet .

Es scheint, dass sich die Anleitung in diesem Bereich geändert hat, da StyleCop jetzt die Verwendung der C # -spezifischen Aliase erzwingt.

Derek Park
quelle
163
Wenn Sie sich für StyleCop entscheiden und dies befolgen, bedeutet dies, dass Sie die sprachspezifischen Typen verwenden. Also für C # haben Sie String (anstelle von String), Int (anstelle von Int32), Float (anstelle von Single) - stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz
144
Ich verwende die Aliase immer, weil ich angenommen habe, dass sie eines Tages nützlich sein könnten, weil sie als Abstraktion fungieren, sodass ihre Implementierungen geändert werden können, ohne dass ich es wissen muss.
Rob
37
In Visual Studio 2015 heißt es, dass String.Format in string.Format geändert werden sollte. Ich denke, Microsoft geht diesen Weg. Ich habe auch immer String für die statischen Methoden verwendet.
Sami Kuhmonen
32
Während ich diese durchgelesen habe, habe ich festgestellt, dass einige der Kommentare einfach falsch sind. @ DRAirey1 Mit der Zeit werden Sie feststellen, dass der alte Weg immer noch der beste ist. Wenn Sie daran zweifeln, wage ich Sie zu versuchen, C # -Code zu schreiben, ohne Visual Studio zu verwenden. Es ist praktisch unmöglich und eine Situation, die bei der Webentwicklung von Zeit zu Zeit auftritt. @Vlad Sie müssen nichts importieren, um String zu verwenden. @Abhi Dein Kommentar ist sinnlos und gilt auch für string.Format(). @KlitosG Nein, das stimmt nicht. Sie arbeiten alle genau gleich.
Krowe2
46
Könnten Sie eine Bemerkung hinzufügen, dass es tatsächlich einen Unterschied gibt? Zum Beispiel: nameof(string)wird nicht kompiliert, wohingegen nameof(String).
Jeroen Vannevel
3439

Der Vollständigkeit halber hier ein Brain Dump verwandter Informationen ...

Wie andere angemerkt haben, stringist ein Alias ​​für System.String. Sie werden mit demselben Code kompiliert, sodass zur Ausführungszeit keinerlei Unterschiede bestehen. Dies ist nur einer der Aliase in C #. Die vollständige Liste lautet:

object:  System.Object
string:  System.String
bool:    System.Boolean
byte:    System.Byte
sbyte:   System.SByte
short:   System.Int16
ushort:  System.UInt16
int:     System.Int32
uint:    System.UInt32
long:    System.Int64
ulong:   System.UInt64
float:   System.Single
double:  System.Double
decimal: System.Decimal
char:    System.Char

Abgesehen von stringund objectsind die Aliase alle Werttypen. decimalist ein Werttyp, aber kein primitiver Typ in der CLR. Der einzige primitive Typ, der keinen Alias ​​hat, ist System.IntPtr.

In der Spezifikation werden die Werttyp-Aliase als "einfache Typen" bezeichnet. Literale können für konstante Werte jedes einfachen Typs verwendet werden. Für keine anderen Werttypen stehen Literalformen zur Verfügung. (Vergleichen Sie dies mit VB, das DateTimeLiterale zulässt und auch einen Alias ​​dafür hat.)

Es gibt einen Umstand , in dem Sie haben die Aliasnamen verwenden: wenn ausdrücklich ein ENUM zugrunde liegenden Typen angeben. Zum Beispiel:

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid

Das ist nur eine Frage der Art und Weise der Spezifikation definiert Enum Erklärungen - der Teil nach dem Doppelpunkt hat das seine Integral-Typ - Produktion, die ein Zeichen ist sbyte, byte, short, ushort, int, uint, long, ulong, char... im Gegensatz zu einer Art Produktion wird beispielsweise von Variablendeklarationen verwendet. Es zeigt keinen anderen Unterschied an.

Schließlich, wenn es darum geht, was zu verwenden ist: Ich persönlich verwende die Aliase überall für die Implementierung, aber den CLR-Typ für alle APIs. Es ist wirklich nicht so wichtig, was Sie für die Implementierung verwenden - die Konsistenz in Ihrem Team ist nett, aber niemand anderes wird sich darum kümmern. Andererseits ist es wirklich wichtig, dass Sie, wenn Sie in einer API auf einen Typ verweisen, dies sprachneutral tun. Eine aufgerufene Methode ReadInt32ist eindeutig, während eine aufgerufene Methode ReadInteine Interpretation erfordert. Der Anrufer könnte beispielsweise eine Sprache verwenden, für die ein intAlias definiert ist Int16. Die .NET Framework - Designer haben dieses Muster gefolgt, gute Beispiele in den zu sein BitConverter, BinaryReaderund ConvertKlassen.

Jon Skeet
quelle
82
Die Vererbungssituation mit Enum ist interessant. Können Sie auf die Dokumentation verweisen, warum Alias ​​für Aufzählungen verwendet werden muss? Oder ist das ein bekannter Fehler?
JaredPar
149
Es befindet sich in Abschnitt 14.1 der Spezifikation (ich kann hier nicht einfach zitieren, da es zu lang ist). Es muss nicht explizit sagen , dass Sie die Aliasnamen verwenden haben, aber die Aliase sind Art als ihre eigene Art behandelt. Es ist alles ein bisschen komisch.
Jon Skeet
32
@PiPeep Was erstaunlicher ist als die große Anzahl an Upvotes, ist die erstaunlich geringe Anzahl an Downvotes (bedenken Sie, dass die Top-5-Beiträge insgesamt über 2000 Upvotes haben und dennoch nur 1 Downvote unter allen). Besonders wenn man bedenkt, dass es in jeder Community immer "Hasser" gibt, finde ich das einfach unglaublich.
CorsiKa
40
Ein interessanter Unterschied zwischen stringund Stringist, dass string' is a keyword in c#, so you can not use it as a variable name.For Ex: string string = "hi"; //compiler error, but String String = "hi"; `ist akzeptabel, ebenso Stringwie ein Identifire kein Schlüsselwort.
Sanjeev Rai
33
@ SanjeevRai: Ja. Sie können @stringeine Kennung erstellen, die so endet, als stringob. Es ist eine Art Fluchtmechanismus.
Jon Skeet
716

Stringsteht für System.Stringund es ist ein .NET Framework-Typ. stringist ein Alias in der C # -Sprache für System.String. Beide sind System.Stringin IL (Intermediate Language) kompiliert , daher gibt es keinen Unterschied. Wählen Sie, was Sie mögen und verwenden Sie das. Wenn Sie in C # codieren, würde ich es vorziehen, stringda es sich um einen Alias ​​vom Typ C # handelt, der C # -Programmierern bekannt ist.

Ich kann das gleiche über ( int, System.Int32) etc .. sagen .

artur02
quelle
3
`Wenn Sie in C # codieren, würde ich eine Zeichenfolge bevorzugen, da es sich um einen C # -Alias ​​handelt, der C # -Programmierern bekannt ist` - wann würde eine C # -Person das .NET-Framework nicht kennen. +1, wie ich allgemein denke, ist dies die beste Antwort, aber der Punkt, den ich erwähne, scheint seltsam.
MyDaftQuestions
4
Ich persönlich bevorzuge "Int32", da es sofort den Wertebereich anzeigt. Stellen Sie sich vor, sie hätten den Typ "int" auf späteren Systemen mit höheren Bits aktualisiert. 'int' in c wird anscheinend als "der ganzzahlige Typ angesehen, mit dem der Zielprozessor am effizientesten arbeitet" und als "mindestens 16 Bit" definiert. Ich würde dort eine vorhersehbare Konsistenz bevorzugen, vielen Dank.
Nyerguds
2
@ MyDaftQuestions Ich stimme zu. Wenn überhaupt, wäre es sinnvoll, die .net-Typen konsequent zu verwenden, da sie sprachunabhängig sind und der Typ offensichtlich ist, unabhängig von einer Sprache (kenne ich alle Eigenheiten von F # oder VB?).
Peter - Monica am
5
@Nyerguds Es gibt zwei Gründe, sich einfach keine Sorgen zu machen. Eine davon ist, dass intin der C # -Sprachenspezifikation unabhängig von der Hardware eine 32-Bit-Ganzzahl definiert ist. C # ist trotz eines gemeinsamen Erbes im Nebel der Zeit nicht wirklich C. Das Ändern intauf eine 64-Bit-Ganzzahl wäre eine bahnbrechende Änderung der Spezifikation und der Sprache. Es würde auch eine Neudefinition erfordern long, wie longes derzeit die 64-Bit-Ganzzahl ist. Der andere Grund, sich keine Sorgen zu machen, ist irrelevant, da sich die Typen nie ändern werden, aber .NET ist nur abstrakt genug, dass Sie in 99% der Fälle sowieso nicht darüber nachdenken müssen. ;-)
Craig
5
@Craig ich in vielen alten proprietären Spiel Formate graben , wo ich Sie über die die ganze Zeit denken, though. Und dann mit Int16, Int32und Int64ist ein viel transparenter im Code als das eher nichts sagende verwenden short, intundlong
Nyerguds
505

Die beste Antwort, die ich je über die Verwendung der bereitgestellten Typ-Aliase in C # gehört habe, stammt von Jeffrey Richter in seinem Buch CLR Via C # . Hier sind seine 3 Gründe:

  • Ich habe eine Reihe von Entwicklern verwirrt gesehen, die nicht wussten, ob sie String oder String in ihrem Code verwenden sollen. Da in C # die Zeichenfolge (ein Schlüsselwort) genau System.String (einem FCL-Typ) zugeordnet ist, gibt es keinen Unterschied und beide können verwendet werden.
  • In C #, langen Karten zu System.Int64 , aber in einer anderen Programmiersprache, lange auf eine Karte könnte Int16 oder Int32 . Tatsächlich behandelt C ++ / CLI lange als Int32 . Jemand, der Quellcode in einer Sprache liest, kann die Absicht des Codes leicht falsch interpretieren, wenn er oder sie es gewohnt ist, in einer anderen Programmiersprache zu programmieren. Tatsächlich behandeln die meisten Sprachen nicht einmal lange als Schlüsselwort und kompilieren keinen Code, der es verwendet.
  • Die FCL verfügt über viele Methoden, deren Methodennamen Typnamen enthalten. Beispielsweise bietet der Typ BinaryReader Methoden wie ReadBoolean , ReadInt32 , ReadSingle usw., und der Typ System.Convert bietet Methoden wie ToBoolean , ToInt32 , ToSingle usw. an. Obwohl es legal ist, den folgenden Code zu schreiben, fühlt sich die Zeile mit float für mich sehr unnatürlich an, und es ist nicht offensichtlich, dass die Zeile korrekt ist:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Da haben Sie es also. Ich denke, das sind alles wirklich gute Punkte. Ich verwende jedoch nicht Jeffreys Ratschläge in meinem eigenen Code. Vielleicht stecke ich zu sehr in meiner C # -Welt fest, aber am Ende versuche ich, meinen Code wie den Framework-Code aussehen zu lassen.

Luke Foust
quelle
24
Der zweite Punkt klingt eigentlich wie ein Grund, nicht zu verwenden string, intetc.
MauganRa
15
@MauganRa Und es soll, der Autor des Buches listet diese Gründe auf, warum er keine Aliase verwendet.
tomi.lee.jones
31
"Wenn jemand C # -Quellcode liest, sollte er lange gemäß der Sprachspezifikation interpretieren, nicht gemäß einer anderen Sprachspezifikation." Das geht völlig daneben. Es ist nicht so, dass irgendjemand beabsichtigt , Code falsch zu interpretieren, es ist einfach leicht für das Gehirn, zu einer falschen Schlussfolgerung zu gelangen, wenn ein Typ eine andere Bedeutung hat als das, was der Programmierer täglich in einem anderen Kontext sieht. Wir alle machen Fehler; Die Verwendung explizit benannter Typen verringert die Wahrscheinlichkeit dieser Fehler.
Darryl
10
+ Diese Gründe fassen meine Gefühle in dieser Angelegenheit zusammen. Als ich anfing, in C # zu programmieren (aus einem Java / C ++ / C-Hintergrund), fand ich die Aliase hässlich. Ich fühle mich immer noch so, leider scheint mir der größte Teil der Welt nicht zuzustimmen, oder es ist ihnen egal, und benutze daher Kleinbuchstaben.
Gusgorman
8
@jinzai Die Frage bezieht sich auf C #, in dem longeine vorzeichenbehaftete 64-Bit-Ganzzahl definiert ist, unabhängig von der Plattform oder dem Compiler. So in einigen Fällen zumindest, ja, es ist von der Sprache abhängig.
Phoog
455

stringist ein reserviertes Wort, aber Stringnur ein Klassenname. Dies bedeutet, dass stringdies nicht als Variablenname verwendet werden kann.

Wenn Sie aus irgendeinem Grund eine Variable namens string möchten, wird nur die erste dieser Kompilierungen angezeigt:

StringBuilder String = new StringBuilder();  // compiles
StringBuilder string = new StringBuilder();  // doesn't compile 

Wenn Sie wirklich einen Variablennamen namens string möchten , können Sie ihn @als Präfix verwenden:

StringBuilder @string = new StringBuilder();

Ein weiterer kritischer Unterschied: Der Stapelüberlauf hebt sie unterschiedlich hervor.

Simon_Weaver
quelle
20
Denken Sie daran, dass das Anrufen eines Einheimischen @stringwirklich ziemlich sinnlos ist, da die Namen der Einheimischen nur in PDBs vorhanden sind. Könnte es auch so nennen _stringoder so. Es ist sinnvoller für Dinge, deren Namen über Reflexion zugänglich sind, wo der Name eines @stringMitglieds wäre "string".
Roman Starkov
25
Denken Sie auch daran, dass die Verwendung eines reservierten Wortes als Variablenname völlig unelegant ist.
Elton
7
Das OP möchte keinen String oder String als Variablennamen verwenden. Sie baten um eine Erklärung des Unterschieds zwischen diesen Typen . Ihre Antwort dient nur dazu, mehr Verwirrung zu stiften IMO
Matt Wilko
1
@craig, wenn Sie Software schreiben, um Menschen das Knüpfen von Knoten beizubringen?
Simon_Weaver
5
@ Simon_Weaver Knoten in Strings? haha schön. :-) Natürlich kannst du auch einen alternativen Namen wie Thread auswählen. Warte eine Minute ... D'oh!
Craig
391

Es gibt einen Unterschied - Sie können nicht Stringohne using System;vorher verwenden.

3296
quelle
14
Standardmäßig fügen die meisten Benutzer dies auf irgendeine Weise oben in der Datei hinzu. VS macht dies standardmäßig in den meisten Fällen von nicht allen!
IbrarMumtaz
9
Standardmäßig füge ich nur usingAnweisungen hinzu, die ich benötige, und entferne explizit alles, was ich nicht tue. Power Productivity Tools> "[x] Entfernen und Formatieren von Verwendungen beim Speichern"
JMD
2
@JMD Ich habe die .cs-Vorlagendatei so geändert, dass sie oben nicht einmal using-Anweisungen enthält! Ich habe auch die Klassenvorlage in geändert internal sealed.
ErikE
@JMD Ich hasse diese Funktion. Manchmal werden Änderungen an ansonsten unberührten Dateien vorgenommen, sodass es schwierig ist zu erkennen, welche tatsächlichen Änderungen ein Änderungssatz enthält. Natürlich entferne ich normalerweise "mit Spam", aber nur aktiv, nicht automatisch.
mg30rg
Dies gilt möglicherweise für C #, jedoch nicht für alle .NET-Sprachen. (Powershell importiert standardmäßig den System-Namespace.)
FSCKur
311

Es wurde oben behandelt; Sie können jedoch nicht stringin der Reflexion verwenden. Sie müssen verwenden String.

TraumaPony
quelle
6
Ich verstehe nicht, was diese Antwort bedeutet und warum sie positiv bewertet wurde. Sie können typeof(string)in der Reflexion verwenden. Beispiel eins: if (someMethodInfo.ReturnType == typeof(string)) { ... }Beispiel zwei: var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);Wo müssen Sie verwenden String, nicht string? Wenn Sie Dinge wie Type.GetType("String")oder ausprobieren Type.GetType("string"), findet keiner die Klasse, da der Namespace fehlt. Wenn Sie aus irgendeinem dummen Grund .Nameeinen Typ mit "string"Groß- und Kleinschreibung vergleichen, haben Sie Recht.
Jeppe Stig Nielsen
256

System.Stringist die .NET-Zeichenfolgenklasse - in C # stringist ein Alias ​​für System.String- in der Verwendung sind sie also identisch.

Was die Richtlinien angeht, würde ich mich nicht zu sehr festsetzen und nur das verwenden, worauf Sie Lust haben - es gibt wichtigere Dinge im Leben und der Code wird sowieso der gleiche sein.

Wenn Sie Systeme erstellen, in denen die Größe der von Ihnen verwendeten Ganzzahlen angegeben werden muss und die dazu neigen , usw. zu verwenden Int16, Int32ist die Verwendung möglicherweise natürlicher - und beim Wechseln zwischen verschiedenen .net-Sprachen möglicherweise Dinge verständlicher machen - sonst würde ich string und int verwenden.UInt16UInt32String

Ronnie
quelle
2
Wählen Sie einfach eine aus und seien Sie konsequent. Wenn Sie irgendwo mit einem Hausstil arbeiten, verwenden Sie diesen.
Alan B
3
Leider ist Stil eine persönliche Präferenz und kann zu teuer sein, um ihn in einer großen Codebasis in mehreren Teams ohne dedizierten Codebesitzer durchzusetzen. Es gibt immer wichtigere Dinge, um die man sich kümmern muss, als String gegen String. das bringt uns zurück zu "wichtigeren Dingen im Leben"
aiodintsov
Dies ist definitiv eine Präferenzsache; zum Beispiel: Ich ziehe es zu verwenden short, int, ushort, uintstatt Int16usw. Vor allem , weil das ist , wie ich gelernt hat. Zugegeben, das Int16ist für diejenigen mit weniger Erfahrung leichter sofort zu verstehen. +1 Von mir!
Candleshark
210

Ich bevorzuge .NETaus Formatierungsgründen die großgeschriebenen Typen (anstelle der Aliase). Die .NETTypen sind genauso gefärbt wie andere Objekttypen (die Werttypen sind schließlich richtige Objekte).

Bedingte und Steuer Schlüsselwörter (wie if, switchund return) sind Kleinbuchstaben und farbige dunkelblau (Standard). Und ich hätte lieber nicht die Uneinigkeit in Gebrauch und Format.

Erwägen:

String someString; 
string anotherString; 
StuartLC
quelle
11
Schreiben Sie auch Code wie: Int32 i = 1; Anstelle von int i = 1; ? Scheint inkonsistent, den String-Alias ​​nicht zu verwenden, wenn er verfügbar ist.
Bytedev
29
@nashwan: Eigentlich, ja, ich benutze Int32 i=1;intstead von int i = 1; Ich finde, dass Ersteres in Bezug auf meine Absicht besser lesbar ist: nämlich, dass ich eine 32-Bit-Ganzzahl mit Vorzeichen möchte.
NotMe
5
Nun, ich denke, es hängt alles davon ab, ob der Entwickler glaubt, C # -Code (String) oder .NET-Code (String) zu schreiben. Persönlich denke ich in erster Linie, dass ich C # schreibe (und es ist C #, das .NET verwendet).
Bytedev
7
@Alex: Mein Punkt war einfach, dass ich es vorziehe, in meiner Codierung sehr spezifisch zu sein, um Mehrdeutigkeiten zu beseitigen.
NotMe
22
Auf dem absoluten anderen Ende des Spektrums verwenden, ich fast immer nurvar
tic
192

stringund Stringsind in jeder Hinsicht identisch (außer dem Großbuchstaben "S"). In beiden Fällen gibt es keine Auswirkungen auf die Leistung.

stringIn den meisten Projekten wird aufgrund der Syntaxhervorhebung Kleinbuchstaben bevorzugt

TheSoftwareJedi
quelle
Jeffrey Richter empfiehlt in allen Fällen die Verwendung des CLR-Typs (CLR über C #), um genau die Art von Verwirrung zu vermeiden, die hier auftritt.
Josh
Es ist klar, ob Sie S oder s verwenden, es wird diese Fragen verursacht haben, also stimmen Sie Richter ab. ;)
Brad Wilson
Richter meinte, dass String keine Option sein sollte - Microsoft sollte ihn nicht in der Sprache haben. Richter kann man nicht herabstimmen - er ist eine Legende! :)
Joe Ratzer
1
Ich stimme zu, dass es vielleicht besser gewesen wäre, die Aliase überhaupt nicht zu haben. Aber da wir sie haben, denke ich, dass es in Ordnung ist, sie zu verwenden (aber nicht in Methodennamen usw.)
Jon Skeet
10
"string" ist nicht dasselbe wie "String". Ist bedeutet "System.String". Wenn Sie also "String" verwenden, müssen Sie "using System"
eingeben
185

C # ist eine Sprache, die zusammen mit der CLR verwendet wird.

string ist ein Typ in C #.

System.String ist ein Typ in der CLR.

Wenn Sie C # zusammen mit der CLR verwenden, stringwird diese zugeordnet System.String.

Theoretisch könnten Sie einen C # -Compiler implementieren, der Java-Bytecode generiert. Eine sinnvolle Umsetzung dieser Compiler würde Karte wahrscheinlich stringauf , java.lang.Stringum mit der Java - Laufzeitbibliothek zu interagieren.

Rasmus Faber
quelle
1
stringist kein Typ in C #; Es ist ein reserviertes Wort, das einem Typ in der CLR zugeordnet ist.
CesarGon
@CesarGon: Gemäß ECMA-334, Abschnitt 8.2.1: "C # bietet eine Reihe vordefinierter Typen [...] Die vordefinierten Referenztypen sind Objekt und Zeichenfolge."
Rasmus Faber
10
Gemäß ECMA-334, Abschnitt 9.4.3, ist "Zeichenfolge" ein Schlüsselwort. :-) Ich stimme Ihnen zu, dass "string" ein Typ ist, wenn Sie sich auf die Semantik konzentrieren, aber ich würde sagen, es ist ein Schlüsselwort (dh ein reserviertes Wort), wenn Sie sich auf die Syntax konzentrieren. Der Standard unterstützt beide Standpunkte (vielleicht zu vieldeutig!). Für mich geht es beim OP um Syntax, daher konzentriere ich mich beim Betrachten von Antworten eher auf die Syntax, aber ich verstehe auch Ihren Standpunkt. Darüber hinaus kann Ihre Antwort in der jetzigen Form dahingehend interpretiert werden, dass zwei verschiedene Typen existieren: Zeichenfolge und Zeichenfolge, wenn dies nicht der Fall ist. Eins ist eine Abbildung auf das andere.
CesarGon
Lassen Sie uns das klarstellen. 'string' ist ein reservierter Alias. Es ist kein echter Datentyp. Es ist etwas, das auf etwas anderes hinweist. Sie können alle diese Aliase entfernen (oder sie einfach nie verwenden) und haben eine perfekt gute Programmiersprache.
Quarkly
168

Dieses YouTube- Video zeigt praktisch, wie sie sich unterscheiden.

Aber jetzt zu einer langen Textantwort.

Wenn wir darüber sprechen , .NETgibt es zwei verschiedene Dinge ist man dort .NETRahmen und die andere gibt es Sprachen ( C#, VB.NETusw.) , die diesen Rahmen nutzen.

Geben Sie hier die Bildbeschreibung ein

" System.String" aka "String" (Großbuchstabe "S") ist ein .NETFramework-Datentyp, während "string" ein C#Datentyp ist.

Geben Sie hier die Bildbeschreibung ein

Kurz gesagt, "String" ist ein Alias ​​(dasselbe, das mit unterschiedlichen Namen aufgerufen wird) von "string". Technisch gesehen ergeben beide folgenden Code-Anweisungen dieselbe Ausgabe.

String s = "I am String";

oder

string s = "I am String";

Auf die gleiche Weise gibt es Aliase für andere c # -Datentypen, wie unten gezeigt: -

Objekt : System.Object, Zeichenfolge : System.String, Bool : System.Boolean, Byte : System.Byte, Sbyte : System.SByte, Kurz: System.Int16und so weiter

Nun die Millionen-Dollar-Frage aus Sicht des Programmierers. Wann also "String" und "String" verwenden?

Um Verwirrung zu vermeiden, verwenden Sie als erstes eine davon konsequent. Aus Sicht der Best Practices ist es jedoch sinnvoll, "string" (kleine "s") zu verwenden, wenn Sie eine Variablendeklaration durchführen. Wenn Sie sie als Klassennamen verwenden, wird "String" (Großbuchstaben "S") bevorzugt.

Im folgenden Code ist die linke Seite eine Variablendeklaration und wird mit "string" deklariert. Auf der rechten Seite rufen wir eine Methode auf, damit "String" sinnvoller ist.

string s = String.ToUpper() ;
Shivprasad Koirala
quelle
25
"Kurz gesagt" String "ist ein Alias ​​(dasselbe mit unterschiedlichen Namen) von" string "". Dies ist nicht korrekt: Der Alias ​​ist "string".
Xavier Egea
3
Wenn Sie eine Variablendeklaration durchführen, ist es gut, "string" (kleines "s") zu verwenden. Wenn Sie es als Klassennamen verwenden, wird "String" (Großbuchstabe "S") bevorzugt. Diese Konvention scheint nicht mehr gültig zu sein: Wenn Sie Visual Studio 2015 verwenden und versuchen, Stringes zu schreiben , schlagen Sie vor, "Ihren Code zu vereinfachen" und ihn an string...
Massimiliano Kraus
165

Kleinbuchstaben stringsind ein Alias ​​für System.String. Sie sind die gleichen in C#.

Es gibt eine Debatte darüber , ob Sie die Systemtypen verwenden sollen ( System.Int32, System.Stringusw.) Typen oder die C# aliases( int, stringusw.). Ich persönlich glaube, Sie sollten das verwenden C# aliases, aber das ist nur meine persönliche Präferenz.

Urini
quelle
4
Das ist das Problem, sie sind keine C # -Aliasnamen, sondern C-Aliase. Es gibt keinen nativen 'String' oder 'Int' in der C # -Sprache, nur syntaktischen Zucker.
Quarkly
16
Ich bin mir nicht sicher, woher "C" stammt, da die C # 5-Sprachspezifikation lautet: "Die Schlüsselwortzeichenfolge ist einfach ein Alias ​​für die vordefinierte Klasse System.String." auf Seite 85, Absatz 4.2.4. Alle Hochsprachen sind syntaktischer Zucker über CPU-Befehlssätzen und Bytecode.
Aiodintsov
156

stringist nur ein Alias ​​für System.String. Der Compiler behandelt sie identisch.

Der einzige praktische Unterschied ist die Syntaxhervorhebung, die Sie erwähnen, und die Sie schreiben müssen, using Systemwenn Sie verwenden String.

Hallgrim
quelle
Sie müssen dem System kein Präfix voranstellen, um String verwenden zu können.
Joe Ratzer
18
Sie müssen ein using Systembei der Verwendung einschließen String, sonst erhalten Sie die folgende Fehlermeldung:The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
Ronald
143

Beide sind gleich. Aber von Code - Richtlinien Sicht ist es besser , zu verwenden , stringstatt String. Dies ist, was Entwickler im Allgemeinen verwenden. zB anstatt zu verwenden, verwenden Int32wir intwie es intist Alias ​​zuInt32

Zu Ihrer Information: "Die Schlüsselwortzeichenfolge ist einfach ein Alias ​​für die vordefinierte Klasse System.String." - C # -Sprachspezifikation 4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx

Pradeep Kumar Mishra
quelle
120

Wie die anderen sagen, sind sie gleich. StyleCop Regeln, standardmäßig werden erzwingen Sie verwendet stringals C # -Code - Stil Best Practice, außer wenn Referenzierung System.Stringstatische Funktionen, wie zum Beispiel String.Format, String.Join, String.Concat, etc ...

Lloyd Cotten
quelle
4
Mir war nicht bewusst, dass StyleCop die Verwendung von Strings kennzeichnen würde - mit Ausnahme statischer Methoden. Ich finde das großartig, da ich es immer so benutze: Zeichenfolge für Typdeklarationen und Zeichenfolge, wenn ich auf die statischen Elemente zugreife.
Goyuix
101

Neue Antwort nach 6 Jahren und 5 Monaten (Aufschub).

Während stringes sich um ein reserviertes C # -Schlüsselwort handelt, das immer eine feste Bedeutung hat, Stringhandelt es sich nur um eine gewöhnliche Kennung, die sich auf alles beziehen kann. Abhängig von den Mitgliedern des aktuellen Typs können der aktuelle Namespace und die angewendeten usingAnweisungen sowie deren Platzierung Stringein anderer Wert oder Typ sein global::System.String.

Ich werde zwei Beispiele nennen, bei denen usingRichtlinien nicht helfen werden .


Erstens, wann Stringist ein Wert des aktuellen Typs (oder eine lokale Variable):

class MySequence<TElement>
{
  public IEnumerable<TElement> String { get; set; }

  void Example()
  {
    var test = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
  }
}

Das oben Gesagte wird nicht kompiliert, da IEnumerable<>kein nicht statisches Element aufgerufen Formatwird und keine Erweiterungsmethoden angewendet werden. In dem obigen Fall kann es immer noch möglich sein, Stringin anderen Kontexten zu verwenden, in denen ein Typ syntaktisch die einzige Möglichkeit ist. Zum Beispiel String local = "Hi mum!";könnte OK sein (abhängig von Namespace und usingDirektiven).

Schlimmer noch: Das Sprichwort String.Concat(someSequence)wird wahrscheinlich (abhängig von usings) zur Linq-Erweiterungsmethode gehen Enumerable.Concat. Es wird nicht zur statischen Methode gewechselt string.Concat.


Zweitens, wenn Stringes sich um einen anderen Typ handelt , der im aktuellen Typ verschachtelt ist:

class MyPiano
{
  protected class String
  {
  }

  void Example()
  {
    var test1 = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
    String test2 = "Goodbye";
  }
}

Keine der Anweisungen in der ExampleMethode wird kompiliert. Hier Stringist immer ein Klavier - String , MyPiano.String. Es ist kein Mitglied darauf vorhanden ( staticoder nicht) Format(oder es wird von seiner Basisklasse geerbt). Und der Wert "Goodbye"kann nicht in ihn umgewandelt werden.

Jeppe Stig Nielsen
quelle
4
Ich nehme an, teuflisch zu sein, könnte man: using String = System.Int32; using Int32 = System.String; und dann die Käfer zählen.
Steve
7
Das ist die richtige Antwort. stringist System.String. Stringkönnte alles sein.
Dave Cousineau
Einverstanden mit DaveCousineau - das ist der Punkt des Alias. Sie können einen anderen StringTyp erstellen , der nicht auf das System.String-Objekt festgelegt wird. Check out: blog.paranoidcoding.com/2019/04/08/…
Kristopher
"Das Schlüsselwort stringhat in C # eine konkrete Bedeutung. Es ist der Typ, System.Stringder in der Kernlaufzeitassembly vorhanden ist. Die Laufzeit versteht diesen Typ von sich aus und bietet die Funktionen, die Entwickler stringsin .NET erwarten . Seine Anwesenheit ist für C # so wichtig, dass dies nicht der Fall ist." Der Compiler wird beendet, bevor er versucht, eine Codezeile zu analysieren. Daher stringhat er eine genaue, eindeutige Bedeutung im C # -Code. Der Bezeichner Stringhat jedoch keine konkrete Bedeutung in C #. Er ist ein Bezeichner, der alle Regeln für die Namenssuche durchläuft as Widget, Studentetc ... "
Kristopher
3
Auf Meta diskutiert
Patrick Artner
99

Die Verwendung von Systemtypen erleichtert die Portierung zwischen C # und VB.Net, wenn Sie sich für solche Dinge interessieren.

Ishmael
quelle
1
Das Konvertieren zwischen C # und VB.NET ist so einfach wie es ist. developerfusion.com/tools/convert/vb-to-csharp
gewähren Sie den
87

Gegen das, was unter anderen Programmierern üblich zu sein scheint, ziehe ich es Stringvor string, nur um die Tatsache hervorzuheben, dass Stringes sich um einen Referenztyp handelt, wie Jon Skeet erwähnte.

RolandK
quelle
78

Ich möchte dies nur zu lfousts Antwort aus Ritchers Buch hinzufügen:

In der C # -Sprachenspezifikation heißt es: "Aus Gründen des Stils wird die Verwendung des Schlüsselworts der Verwendung des vollständigen Systemtypnamens vorgezogen." Ich bin mit der Sprachspezifikation nicht einverstanden; Ich bevorzuge die Verwendung der FCL-Typnamen und vermeide die primitiven Typnamen vollständig. Tatsächlich wünschte ich mir, dass Compiler nicht einmal die primitiven Typnamen anbieten und Entwickler dazu zwingen würden, stattdessen die FCL-Typnamen zu verwenden. Hier sind meine Gründe:

  • Ich habe eine Reihe von Entwicklern verwirrt gesehen, die nicht wussten, ob sie String oder String in ihrem Code verwenden sollen. Da in C # Zeichenfolge (ein Schlüsselwort) bildet genau System.String (FCL - Typ), gibt es keinen Unterschied und kann entweder verwendet werden. In ähnlicher Weise habe ich einige Entwickler sagen hören, dass int eine 32-Bit-Ganzzahl darstellt, wenn die Anwendung auf einem 32-Bit-Betriebssystem ausgeführt wird, und dass es eine 64-Bit-Ganzzahl darstellt, wenn die Anwendung auf einem 64-Bit-Betriebssystem ausgeführt wird. Diese Anweisung ist absolut falsch: In C # wird ein int immer System.Int32 zugeordnet und stellt daher eine 32-Bit-Ganzzahl dar, unabhängig davon , auf welchem Betriebssystem der Code ausgeführt wird. Wenn Programmierer verwenden würdenInt32 in ihrem Code, dann wird diese mögliche Verwirrung auch beseitigt.

  • In C #, langen Karten zu System.Int64 , aber in einer anderen Programmiersprache, lange auf eine Karte könnte Int16 oder Int32 . Tatsächlich behandelt C ++ / CLI lange wie ein Int32 . Jemand, der Quellcode in einer Sprache liest, kann die Absicht des Codes leicht falsch interpretieren, wenn er oder sie es gewohnt ist, in einer anderen Programmiersprache zu programmieren. Tatsächlich behandeln die meisten Sprachen nicht einmal lange als Schlüsselwort und kompilieren keinen Code, der es verwendet.

  • Die FCL verfügt über viele Methoden, deren Methodennamen Typnamen enthalten. Beispielsweise bietet der Typ BinaryReader Methoden wie ReadBoolean , ReadInt32 , ReadSingle usw., und der Typ System.Convert bietet Methoden wie ToBoolean , ToInt32 , ToSingle usw. Obwohl es legal ist, den folgenden Code zu schreiben, fühlt sich die Zeile mit float für mich sehr unnatürlich an, und es ist nicht offensichtlich, dass die Zeile korrekt ist:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • Viele Programmierer, die ausschließlich C # verwenden, neigen dazu zu vergessen, dass andere Programmiersprachen gegen die CLR verwendet werden können, und aus diesem Grund schleichen sich C # -Iismen in den Klassenbibliothekscode ein. Zum Beispiel wird FCL Microsoft fast ausschließlich in C # geschrieben und Entwickler auf dem FCL - Team hat nun Methoden in die Bibliothek wie eingeführt Array ‚s GetLongLength , die einen zurück Int64 Wertes, der eine ist lange in C # , aber nicht in anderen Sprachen (wie C ++ / CLI). Ein weiteres Beispiel ist die LongCount - Methode von System.Linq.Enumerable .

Ich habe seine Meinung nicht verstanden, bevor ich den vollständigen Absatz gelesen habe.

Otiel
quelle
72

String ( System.String) ist eine Klasse in der Basisklassenbibliothek. Zeichenfolge (Kleinbuchstaben) ist eine reservierte Arbeit in C #, die ein Alias ​​für System.String ist. Int32 vs int ist eine ähnliche Situation wie sie ist Boolean vs. bool. Mit diesen sprachspezifischen C # -Schlüsselwörtern können Sie Grundelemente in einem ähnlichen Stil wie C deklarieren.

Joe Alfano
quelle
67

Stringist kein Schlüsselwort und kann als Bezeichner verwendet werden, während stringes sich um ein Schlüsselwort handelt und nicht als Bezeichner verwendet werden kann. Und aus funktionaler Sicht sind beide gleich.

576533
quelle
67

Es ist wirklich eine Frage der Konvention. stringsieht eher nach C / C ++ aus. Die allgemeine Konvention besteht darin, die von Ihrer gewählten Sprache bereitgestellten Verknüpfungen zu verwenden (int / Int für Int32). Dies gilt auch für "Objekt" decimal.

Theoretisch könnte dies helfen, Code in einen zukünftigen 64-Bit-Standard zu portieren, in dem "int" bedeuten könnte Int64, aber das ist nicht der Punkt, und ich würde erwarten, dass jeder Upgrade-Assistent aus Sicherheitsgründen intVerweise auf Int32ohnehin ändert .

Mel
quelle
66

Zu spät zur Party kommen: Ich benutze die CLR-Typen 100% der Zeit (naja, außer wenn ich gezwungen bin, den C # -Typ zu verwenden, aber ich erinnere mich nicht, wann das letzte Mal war).

Ich habe ursprünglich vor Jahren damit begonnen, gemäß den CLR-Büchern von Ritchie. Für mich war es sinnvoll, dass alle CLR-Sprachen letztendlich in der Lage sein müssen, den Satz von CLR-Typen zu unterstützen, sodass die Verwendung der CLR-Typen selbst einen klareren und möglicherweise "wiederverwendbareren" Code liefert.

Jetzt, wo ich es seit Jahren mache, ist es eine Gewohnheit und ich mag die Färbung, die VS für die CLR-Typen zeigt.

Der einzige wirkliche Nachteil ist, dass die automatische Vervollständigung den C # -Typ verwendet, sodass ich am Ende automatisch generierte Typen erneut tippe, um stattdessen den CLR-Typ anzugeben.

Wenn ich jetzt "int" oder "string" sehe, sieht es für mich einfach falsch aus, als würde ich den C-Code der 1970er Jahre betrachten.

Michael Ray Lovett
quelle
49

Es gibt keinen Unterschied.

Das C # -Schlüsselwort stringwird dem .NET-Typ zugeordnet System.String- es ist ein Alias, der die Namenskonventionen der Sprache einhält.

Ebenso intKarten zu System.Int32.

Oded
quelle
In einem 64-Bit-Build wird int System.Int64 (8 Byte) zugeordnet, in einem 32-Bit-Build wird System.Int32 (4 Byte) zugeordnet
Alex
1
IntPtr und UIntPtr sind die einzigen Typen, deren Größe sich je nach Plattform ändert (wobei tatsächlicheint* Zeigertypen wie und Typen, die aus [U] IntPtrs oder tatsächlichen Zeigern bestehen, nicht berücksichtigt werden).
P Daddy
45

Es gibt ein Zitat zu diesem Thema aus Daniel Solis 'Buch .

Alle vordefinierten Typen werden direkt den zugrunde liegenden .NET-Typen zugeordnet. Die C # -Typnamen (Zeichenfolge) sind einfach Aliase für die .NET-Typen (Zeichenfolge oder System.String). Daher funktioniert die Verwendung der .NET-Namen syntaktisch einwandfrei, obwohl davon abgeraten wird. In einem C # -Programm sollten Sie die C # -Namen anstelle der .NET-Namen verwenden.

Benutzer2771704
quelle
41

Zeichenfolge ist ein Schlüsselwort, und Sie können Zeichenfolge nicht als Bezeichner verwenden.

String ist kein Schlüsselwort und kann als Bezeichner verwendet werden:

Beispiel

string String = "I am a string";

Das Schlüsselwort string ist ein Alias, denn System.Stringabgesehen vom Schlüsselwortproblem sind die beiden genau gleichwertig.

 typeof(string) == typeof(String) == typeof(System.String)
CoreDeveloper
quelle
2
Der einzige winzige Unterschied besteht darin, dass Sie bei Verwendung der String-Klasse den System-Namespace über Ihrer Datei importieren müssen, während Sie dies bei Verwendung des String-Schlüsselworts nicht tun müssen.
Uttam
Es gibt einfache Anwendungsfälle, in denen die Gleichheitsanweisung fehlschlagen würde ... Zum Beispiel das Definieren eines Typaufrufs String im blah-Namespace und das Importieren dieses Namespace in die Datei, in der die Gleichheitsanweisung ausgeführt wird.
Rick
40

Ja, das ist kein Unterschied zwischen ihnen, genau wie das boolund Boolean.

Coder
quelle
40

@JaredPar (ein Entwickler des C # -Compilers und produktiver SO-Benutzer!) Hat einen großartigen Blog-Beitrag zu diesem Thema geschrieben. Ich denke, es lohnt sich, hier zu teilen. Es ist eine schöne Perspektive auf unser Thema.

stringvs. Stringist kein Stil Debatte

[...]

Das Schlüsselwort stringhat in C # eine konkrete Bedeutung. Dies ist der Typ, System.Stringder in der Kernlaufzeitassembly vorhanden ist. Die Laufzeit versteht diesen Typ uneingeschränkt und bietet die Funktionen, die Entwickler für Zeichenfolgen in .NET erwarten. Das Vorhandensein ist für C # so wichtig, dass der Compiler beendet wird, wenn dieser Typ nicht vorhanden ist, bevor er versucht, eine Codezeile zu analysieren. Hat daher stringeine genaue, eindeutige Bedeutung im C # -Code.

Der Bezeichner Stringhat jedoch in C # keine konkrete Bedeutung. Es ist ein Bezeichner, wie durch alle Namen - Suche Regeln geht Widget, Studentusw ... Es könnte zu bespannen binden oder es könnte als in einer anderen Baugruppe vollständig , deren Zweck sein kann , ganz anders als ein Typ binden string. Schlimmer noch, es könnte so definiert werden, dass Code wie String s = "hello"; weiter kompilieren.

class TricksterString { 
  void Example() {
    String s = "Hello World"; // Okay but probably not what you expect.
  }
}

class String {
  public static implicit operator String(string s) => null;
}

Die tatsächliche Bedeutung von Stringwird immer von der Namensauflösung abhängen. Das heißt, es hängt von allen Quelldateien im Projekt und allen Typen ab, die in allen Assemblys definiert sind, auf die verwiesen wird. Kurz gesagt, es erfordert einiges an Kontext, um zu wissen, was es bedeutet.

Richtig, dass in den allermeisten Fällen Stringund stringwird an den gleichen Typ binden. Die Verwendung von StringStill bedeutet jedoch, dass Entwickler ihr Programm der Interpretation an Orten überlassen, an denen es nur eine richtige Antwort gibt. Wenn Stringdie Bindung an den falschen Typ erfolgt, können Entwickler stundenlang debuggen, Fehler im Compilerteam melden und im Allgemeinen Zeit verschwenden, die durch die Verwendung hätte eingespart werden können string.

Eine andere Möglichkeit, den Unterschied zu visualisieren, ist dieses Beispiel:

string s1 = 42; // Errors 100% of the time  
String s2 = 42; // Might error, might not, depends on the code

Viele werden argumentieren, dass die Verwendung technisch korrekter Informationen Stringimmer noch in Ordnung ist, da es äußerst selten vorkommt, dass eine Codebasis einen Typ dieses Namens definiert. Oder wenn Stringes definiert ist, ist es ein Zeichen für eine schlechte Codebasis.

[...]

Sie werden sehen , dass Stringfür eine Reihe von vollständig gültig Zwecke definiert ist: Reflexion Helfer, Serialisierung Bibliotheken, lexers, Protokolle, etc ... Für jede dieser Bibliotheken Stringvs. stringhat reale Folgen je nachdem , wo der Code verwendet wird.

Denken Sie also daran, wenn Sie die Stringvs.- stringDebatte sehen, geht es um Semantik, nicht um Stil. Wenn Sie eine Zeichenfolge auswählen, erhält Ihre Codebasis eine klare Bedeutung. Die Wahl Stringist nicht falsch, lässt aber die Tür für Überraschungen in der Zukunft offen.

Hinweis: Ich habe den größten Teil des Blogposts aus Archivgründen kopiert / eingefügt. Ich ignoriere einige Teile, daher empfehle ich, den Blog-Beitrag zu überspringen und zu lesen, wenn Sie können.

aloisdg
quelle