Qual è la differenza tra String e string in C #?


6511

Esempio ( notare il caso ):

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

Quali sono le linee guida per l'uso di ciascuno? E quali sono le differenze?


72
@ORMapper, ma resta il fatto che stringè un costrutto lessicale della grammatica C # mentre System.Stringè solo un tipo. Indipendentemente da qualsiasi differenza esplicita menzionata in qualsiasi specifica, esiste ancora questa differenza implicita che potrebbe essere compensata da una certa ambiguità. Il linguaggio stesso deve supportare stringin modo tale che l'implementazione non sia (del tutto) così obbligata a prendere in considerazione una determinata classe nel BCL.
Kirk Woll,

106
@KirkWoll: secondo le specifiche del linguaggio, il linguaggio stesso deve considerare stringesattamente lo stesso del tipo BCL System.String, nient'altro. Questo non è affatto ambiguo. Ovviamente, puoi implementare il tuo compilatore, usando la grammatica C #, e usare tutti i token trovati così per qualcosa di arbitrario, non correlato a ciò che è definito nelle specifiche del linguaggio C #. Tuttavia, la lingua risultante sarebbe solo un sosia di C #, non poteva essere considerata C #.
OR Mapper

88
È possibile utilizzare stringsenza una direttiva using per System. Non puoi farlo con String.
Wilsu,

14
Per qualcuno che viene dall'Algol e da Fortran, questa discussione mostra che c'è qualcosa che non va string. È necessario abbreviare System.String, ma, come alias, sembra abbastanza, ma non esattamente la stessa cosa. Dopo diversi anni di C #, però, direi, è sicuro di usare semplicemente stringe string.Format()e di non preoccuparsi System.String.
Roland,

8
@Sangeeta Cosa stai dicendo? La System.Stringclasse è ancora lì e la stringparola chiave è ancora un alias per questo. Proprio come System.Int32e int. Sono letteralmente la stessa cosa.
Craig,

Risposte:


6106

stringè un alias in C # per System.String.
Quindi tecnicamente, non c'è differenza. E 'come int contro System.Int32 .

Per quanto riguarda le linee guida, in genere si consiglia di utilizzare stringogni volta che ci si riferisce a un oggetto.

per esempio

string place = "world";

Allo stesso modo, penso che sia generalmente raccomandato l'uso Stringse è necessario fare riferimento in modo specifico alla classe.

per esempio

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

Questo è lo stile che Microsoft tende ad usare nei loro esempi .

Sembra che la guida in quest'area possa essere cambiata, poiché StyleCop ora impone l'uso degli alias specifici di C #.


163
Se decidi di usare StyleCop e seguirlo, ciò ti dirà di usare i tipi specifici della lingua. Quindi per C # avrai string (invece di String), int (invece di Int32), float (invece di Single) - stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz

144
Uso sempre gli alias perché ho pensato che un giorno potrebbe tornare utile perché si comportano come un'astrazione, quindi è possibile che le loro implementazioni vengano modificate senza che me ne accorga.
Rob,

37
Visual Studio 2015 afferma che String.Format dovrebbe essere modificato in string.Format, quindi immagino che Microsoft stia andando in quel modo. Ho sempre usato String per i metodi statici.
Sami Kuhmonen,

32
Mentre ho letto questi, ho notato che molti dei commenti sono semplicemente errati. @ DRAirey1 Col tempo, scoprirai che il vecchio modo è ancora il migliore, se ne dubiti, allora ti sfido a provare a scrivere il codice C # senza usare Visual Studio. È praticamente impossibile e una situazione che si presenta di volta in volta nel lavoro di sviluppo web. @Vlad Non è necessario importare nulla per utilizzare String. @Abhi Il tuo commento è inutile e altrettanto vero per string.Format(). @KlitosG No, non è vero. Funzionano tutti esattamente allo stesso modo.
krowe2,

46
Potresti aggiungere un'osservazione che in realtà c'è una differenza? Ad esempio: nameof(string)non compilerà mentre lo nameof(String)farà.
Jeroen Vannevel,

3440

Solo per completezza, ecco una discarica di informazioni correlate ...

Come altri hanno notato, stringè un alias per System.String. Si compilano con lo stesso codice, quindi al momento dell'esecuzione non c'è alcuna differenza. Questo è solo uno degli alias in C #. L'elenco completo è:

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

A parte stringe object, gli alias sono tutti di tipi di valore. decimalè un tipo di valore, ma non un tipo primitivo nel CLR. L'unico tipo primitivo che non ha un alias è System.IntPtr.

Nella specifica, gli alias del tipo di valore sono noti come "tipi semplici". I letterali possono essere usati per valori costanti di ogni tipo semplice; nessun altro tipo di valore ha forme letterali disponibili. (Confronta questo con VB, che consente i DateTimeletterali e ha anche un alias per esso.)

V'è una circostanza in cui si deve usare gli alias: quando si specifica in modo esplicito tipo sottostante di un enum. Per esempio:

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

Questo è solo un aspetto del modo in cui definisce enum dichiarazioni spec - la parte dopo il colon deve essere l' integrale di tipo di produzione, che è un gettone di sbyte, byte, short, ushort, int, uint, long, ulong, char... al contrario di un tipo di produzione utilizzato ad esempio da dichiarazioni di variabili. Non indica alcuna altra differenza.

Infine, quando si tratta di quale utilizzare: personalmente uso gli alias ovunque per l'implementazione, ma il tipo CLR per qualsiasi API. In realtà non importa molto quale usi in termini di implementazione: la coerenza tra il tuo team è buona, ma a nessuno importa. D'altra parte, è veramente importante che se si fa riferimento a un tipo in un'API, lo si fa in modo neutrale rispetto al linguaggio. Un metodo chiamato ReadInt32non è ambiguo, mentre un metodo chiamato ReadIntrichiede interpretazione. Ad esempio, il chiamante potrebbe utilizzare una lingua che definisce un intalias Int16. I progettisti di .NET framework hanno seguito questo schema, un buon esempio essendo nelle BitConverter, BinaryReadere Convertclassi.


82
La situazione ereditaria con enum è interessante. Puoi indicare la documentazione sul perché l'alias deve essere usato per le enumerazioni? O è un bug noto?
JaredPar,

149
È nella sezione 14.1 delle specifiche (non posso citare qui facilmente perché è troppo lungo). Non dice esplicitamente che hai avuto modo di utilizzare l'alias, ma gli alias sono una sorta di trattati come i loro propri tipi. È tutto un po 'strano.
Jon Skeet,

32
@PiPeep ciò che è più sorprendente della grande quantità di voti positivi è l'incredibile bassa quantità di voti negativi (considera che i primi 5 post hanno un totale di oltre 2000 voti positivi, eppure solo 1 voto negativo tra tutti). Soprattutto quando si tiene conto del fatto che ci sono sempre "nemici" in qualsiasi comunità, lo trovo davvero semplicemente incredibile.
corsiKa

40
Una differenza interessante tra stringe Stringè quella string' is a keyword in c#, so you can not use it as a variable name.For Ex: stringa stringa = "ciao"; //compiler error, but String String = "hi"; `è accettabile, così come Stringun identificativo non una parola chiave.
Sanjeev Rai,

33
@SanjeevRai: Sì. È possibile utilizzare @stringper creare un identificatore che finisce come stringse. È una sorta di meccanismo di fuga.
Jon Skeet,

716

Stringsta per System.Stringed è un tipo .NET Framework. stringè un alias nel linguaggio C # per System.String. Entrambi sono compilati System.Stringin IL (Intermediate Language), quindi non c'è differenza. Scegli quello che ti piace e usalo. Se codifichi in C #, preferirei stringche sia un alias di tipo C # e ben noto ai programmatori C #.

Posso dire lo stesso di ( int, System.Int32) ecc.


3
"Se codifichi in C #, preferirei la stringa in quanto è un alias di tipo C # e ben noto ai programmatori C #" - quando una persona C # non conosce il framework .NET. +1 come penso generalmente questa è la risposta migliore, ma il punto che cito sembra strano.
MyDaftQuestions

4
Personalmente preferisco usare "Int32", poiché mostra immediatamente l'intervallo del valore. Immagina se aggiornassero il tipo di "int" su sistemi successivi a bit più alto. 'int' in c è apparentemente visto come "il tipo intero con cui il processore di destinazione è più efficiente lavorando" , e definito come "almeno 16 bit". Preferirei una coerenza prevedibile lì, grazie mille.
Nyerguds,

2
@MyDaftQuestions Concordo. Semmai avrebbe senso usare coerentemente i tipi .net perché ignorano la lingua e il tipo è ovvio, indipendente da qualsiasi lingua (conosco tutte le idiosincrasie di F # o VB?).
Peter - Ripristina Monica il

5
@Nyerguds Ci sono due motivi per non preoccuparsene. Uno è quello intdefinito nelle specifiche del linguaggio C # come numero intero a 32 bit indipendentemente dall'hardware. C #, nonostante un'eredità condivisa nella notte dei tempi, in realtà non è C. Passare inta un numero intero a 64 bit sarebbe un cambiamento decisivo nelle specifiche e nella lingua. Richiederebbe anche una ridefinizione long, poiché longattualmente è l'intero a 64 bit. L'altro motivo per non preoccuparsi è irrilevante poiché i tipi non cambieranno mai, ma .NET è abbastanza astratto da non doverci pensare al 99% delle volte. ;-)
Craig

5
@ Craig I dig in lotti di vecchi formati proprietari di gioco dove mi faccio devo pensare che tutto il tempo, però. E poi usando Int16, Int32ed Int64è molto più trasparente nel codice che usare il non shortintlong
descrittivo

506

La migliore risposta che io abbia mai sentito sull'uso dell'alias di tipo fornito in C # viene da Jeffrey Richter nel suo libro CLR Via C # . Ecco i suoi 3 motivi:

  • Ho visto diversi sviluppatori confusi, non sapendo se usare la stringa o la stringa nel loro codice. Perché in C # la stringa (una parola chiave) si associa esattamente a System.String (un tipo FCL), non vi è alcuna differenza ed è possibile utilizzare entrambi.
  • In C #, long esegue il mapping a System.Int64 , ma in un linguaggio di programmazione diverso, long può eseguire il mapping a Int16 o Int32 . In effetti, C ++ / CLI in effetti tratta come Int32 . Qualcuno che legge il codice sorgente in una lingua potrebbe facilmente interpretare male l'intenzione del codice se fosse abituato a programmare in un linguaggio di programmazione diverso. In effetti, la maggior parte delle lingue non tratterà nemmeno a lungo come una parola chiave e non compilerà il codice che la utilizza.
  • La FCL ha molti metodi che hanno nomi di tipi come parte dei loro nomi di metodi. Ad esempio, il tipo BinaryReader offre metodi come ReadBoolean , ReadInt32 , ReadSingle e così via, mentre il tipo System.Convert offre metodi come ToBoolean , ToInt32 , ToSingle e così via. Sebbene sia legale scrivere il seguente codice, la riga con float mi sembra molto innaturale e non è ovvio che la riga sia corretta:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Così il gioco è fatto. Penso che questi siano tutti punti davvero positivi. Tuttavia, non mi ritrovo ad usare i consigli di Jeffrey nel mio codice. Forse sono troppo bloccato nel mio mondo C # ma finisco per provare a rendere il mio codice simile al codice del framework.


24
Il secondo punto sembra in realtà un motivo per non usarlo string, intecc.
MauganRa,

15
@MauganRa E si suppone che l'autore del libro elenchi quei motivi per cui non usa gli alias.
tomi.lee.jones,

31
"Se qualcuno sta leggendo il codice sorgente C #, dovrebbe interpretare a lungo in base alle specifiche della lingua, non alle specifiche di un'altra lingua." Questo non ha pienamente compreso il punto. Non è che nessuno intenda fraintendere il codice, è semplicemente facile per il proprio cervello saltare alla conclusione sbagliata quando un tipo ha un significato diverso da quello che il programmatore vede quotidianamente in un altro contesto. Tutti commettiamo errori; l'uso di tipi con nome esplicito rende questi errori meno probabili.
Darryl,

10
+ Queste ragioni riassumono i miei sentimenti sulla questione. Quando ho iniziato a scrivere codice in C # (proveniente da uno sfondo Java / C ++ / C) pensavo che gli alias fossero brutti. Mi sento ancora così, sfortunatamente la maggior parte del mondo non sembra essere d'accordo con me, o non gliene importa, e quindi usa la minuscola.
Gusgorman,

8
@jinzai la domanda riguarda C #, in cui longè definito come un intero a 64 bit con segno, indipendentemente dalla piattaforma o dal compilatore. Quindi, in alcuni casi almeno, sì, non dipendono dalla lingua.
phoog

456

stringè una parola riservata, ma Stringè solo un nome di classe. Ciò significa che stringnon può essere utilizzato come nome di variabile da solo.

Se per qualche motivo volessi una variabile chiamata stringa , vedresti solo la prima di queste compilazioni:

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

Se vuoi davvero un nome di variabile chiamato stringa puoi usare @come prefisso:

StringBuilder @string = new StringBuilder();

Un'altra differenza fondamentale: Stack Overflow li evidenzia in modo diverso.


20
Tieni presente che chiamare un locale @stringè davvero inutile, poiché i nomi dei locali sono presenti solo nei PDB. Potrebbe anche chiamarlo _stringo qualcosa del genere. Ha più senso per le cose che hanno nomi accessibili tramite la riflessione, dove @stringsarebbe il nome di un membro "string".
Roman Starkov,

25
Inoltre, tieni presente che utilizzare una parola riservata in quanto un nome di variabile è gravemente non elegante.
Elton,

7
L'OP non desidera utilizzare String o String come nome di variabile. Hanno chiesto una spiegazione della differenza tra questi tipi . La tua risposta serve solo per aggiungere più confusione IMO
Matt Wilko

1
@craig se stavi scrivendo software per insegnare alla gente come legare i nodi?
Simon_Weaver

5
@Simon_Weaver nodi in stringhe? ahah carino. :-) Certo, potresti scegliere un nome alternativo, come thread. Aspetta un attimo ... D'oh!
Craig,

392

C'è una differenza : non puoi usarlo Stringsenza using System;prima.


14
per impostazione predefinita la maggior parte delle persone lo aggiunge in qualsiasi modo nella parte superiore del file. VS lo fa di default nella maggior parte dei casi, non tutti!
IbrarMumtaz,

9
Per impostazione predefinita aggiungo solo le usingistruzioni che richiedo e rimuovo esplicitamente tutto ciò che non faccio. Strumenti per la produttività energetica> "[x] Rimuovi e formatta gli utilizzi al salvataggio"
JMD,

2
@JMD Ho modificato il file modello .cs in modo che non abbia nemmeno alcuna istruzione di utilizzo in alto! Ho anche cambiato il modello di classe in internal sealed.
ErikE

@JMD Odio quella caratteristica. A volte apporta modifiche su file altrimenti non toccati rendendo difficile vedere quali modifiche effettive contiene un changeset. Naturalmente di solito rimuovo "usando lo spam", ma solo attivamente, non automaticamente.
mg30rg

Potrebbe essere così per C #, ma non per tutti i linguaggi .NET. (Powershell importa lo spazio dei nomi di sistema per impostazione predefinita.)
FSCKur

312

È stato coperto sopra; tuttavia, non è possibile utilizzare stringnella riflessione; devi usare String.


6
Non capisco cosa significhi questa risposta e perché sia ​​stata votata. Puoi usare typeof(string)in riflessione. Esempio uno: if (someMethodInfo.ReturnType == typeof(string)) { ... }Esempio due: var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);dov'è che devi usare String, no string? Se provi cose come Type.GetType("String")o Type.GetType("string"), nessuna delle due troverà la classe perché manca lo spazio dei nomi. Se per qualche motivo sciocco paragoni .Namedi un tipo a "string"in modo sensibile al maiuscolo / minuscolo, hai ragione.
Jeppe Stig Nielsen

257

System.Stringè la classe di stringhe .NET - in C # stringè un alias per System.String- quindi in uso sono uguali.

Per quanto riguarda le linee guida, non mi impantanerei troppo e utilizzerei semplicemente quello che pensi: ci sono cose più importanti nella vita e il codice sarà lo stesso comunque.

Se vi trovate sistemi in cui è necessario costruire per specificare la dimensione degli interi che si sta utilizzando e quindi tendono ad usare Int16, Int32, UInt16, UInt32ecc allora potrebbe sembrare più naturale da usare String- e durante gli spostamenti tra i diversi linguaggi .net potrebbe rendere le cose più comprensibili, altrimenti userei string e int.


2
Basta sceglierne uno ed essere coerenti. Se lavori da qualche parte con uno stile casalingo, usalo.
Alan B,

3
sfortunatamente lo stile è una preferenza personale e può essere troppo costoso da applicare in una grande base di codice tra più team senza proprietario di codice dedicato. ci sono sempre questioni più importanti di cui occuparsi piuttosto che string vs string. che ci riporta a "cose ​​più importanti nella vita"
aiodintsov,

Questa è sicuramente una cosa di preferenza; per esempio: io preferisco usare short, int, ushort, uintinvece di Int16, ecc Soprattutto perché questo è il modo che ho imparato. Certo, Int16è più facile da capire immediatamente per chi ha meno esperienza. +1 Da parte mia!
Candleshark,

211

Preferisco i .NETtipi maiuscoli (piuttosto che gli alias) per motivi di formattazione. I .NETtipi sono colorati come gli altri tipi di oggetti (i tipi di valore sono oggetti propri, dopo tutto).

Le parole chiave condizionali e di controllo (come if, switche return) sono minuscole e colorate di blu scuro (per impostazione predefinita). E preferirei non avere il disaccordo nell'uso e nel formato.

Prendere in considerazione:

String someString; 
string anotherString; 

11
Scrivi anche codice come: Int32 i = 1; Piuttosto che int i = 1; ? Sembra incoerente non utilizzare l'alias di stringa quando è disponibile.
bytedev,

29
@nashwan: in realtà sì, uso Int32 i=1;intstead di int i = 1; trovo che il primo sia più leggibile per quanto riguarda il mio intento: vale a dire che voglio un intero con segno a 32 bit.
NotMe,

5
Beh, credo che tutto dipenda dal fatto che lo sviluppatore pensi che stiano scrivendo codice C # (stringa) o codice .NET (stringa). Personalmente penso innanzitutto di scrivere C # (ed è C # che utilizza .NET).
bytedev,

7
@Alex: il mio punto era semplicemente che preferivo essere molto specifico nella mia codifica per rimuovere l'ambiguità.
NotMe

22
All'altro capo assoluto dello spettro, uso quasi semprevar
tic il

193

stringe Stringsono identici in tutti i modi (tranne la "S" maiuscola). Non ci sono implicazioni sulle prestazioni in entrambi i casi.

Il carattere minuscolo stringè preferito nella maggior parte dei progetti a causa dell'evidenziazione della sintassi


Jeffrey Richter consiglia di utilizzare il tipo CLR in tutti i casi (CLR via C #) per evitare esattamente il tipo di confusione che si sta verificando qui.
Josh,

Chiaramente, se usi S o s, avrai causato questa domanda, quindi vota in basso Richter. ;)
Brad Wilson,

Richter voleva dire che la stringa non avrebbe dovuto essere un'opzione - Microsoft non dovrebbe averla nella lingua. Non puoi sottovalutare Richter: è una leggenda! :)
Joe Ratzer,

1
Concordo sul fatto che sarebbe stato meglio non avere affatto gli alias. Ma dato che li abbiamo, penso che sia giusto usarli (ma non nei nomi dei metodi, ecc.)
Jon Skeet,

10
"stringa" non è la stessa di "stringa". È significa "System.String". Quindi se usi "String" devi inserire "using System" per includere lo spazio dei nomi
ThiagoAlves il

186

C # è un linguaggio che viene utilizzato insieme al CLR.

string è un tipo in C #.

System.String è un tipo nel CLR.

Quando si utilizza C # insieme al CLR stringverrà mappato System.String.

Teoricamente, potresti implementare un compilatore C # che ha generato il bytecode Java. Un'implementazione sensibile di questo compilatore probabilmente mappa stringper java.lang.Stringal fine di interagire con la libreria di runtime Java.


1
stringnon è un tipo in C #; è una parola riservata che si associa a un tipo nel CLR.
CesarGon,

@CesarGon: Secondo ECMA-334, sezione 8.2.1: "C # fornisce un insieme di tipi predefiniti [...] I tipi di riferimento predefiniti sono oggetto e stringa."
Rasmus Faber,

10
Secondo ECMA-334, sezione 9.4.3, "stringa" è una parola chiave. :-) Concordo con te sul fatto che "stringa" è un tipo se ti concentri sulla semantica, ma direi che è una parola chiave (cioè una parola riservata) se ti concentri sulla sintassi. Lo standard sostiene entrambi i punti di vista (forse in modo troppo ambiguo!). Per me, l'OP riguarda la sintassi, quindi tendo a concentrarmi sulla sintassi quando guardo le risposte, ma vedo anche il tuo punto. Inoltre, la tua risposta, così com'è, può essere interpretata nel senso che esistono due tipi diversi: stringa e stringa, quando non è così. Uno è una mappatura all'altro.
CesarGon,

Cerchiamo di essere chiari su questo. 'stringa' è un alias riservato. Non è un vero tipo di dati. È qualcosa che indica qualcos'altro. Puoi rimuovere tutti questi alias (o semplicemente non usarli mai) e avere un linguaggio di programmazione perfettamente valido.
Quarkly

169

Questo video di YouTube dimostra praticamente come differiscono.

Ma ora per una lunga risposta testuale.

Quando si parla di .NETci sono due cose diverse c'è un .NETquadro e l'altro ci sono lingue ( C#, VB.NETecc) che utilizzano tale contesto.

inserisci qui la descrizione dell'immagine

" System.String" aka "String" (maiuscola "S") è un .NETtipo di dati del framework mentre "string" è un C#tipo di dati.

inserisci qui la descrizione dell'immagine

In breve "String" è un alias (la stessa cosa chiamata con nomi diversi) di "string". Quindi tecnicamente entrambe le istruzioni di codice riportate di seguito daranno lo stesso output.

String s = "I am String";

o

string s = "I am String";

Allo stesso modo ci sono alias per altri tipi di dati c # come mostrato di seguito: -

oggetto: System.Object, stringa: System.String, bool: System.Boolean, byte: System.Byte, sbyte: System.SBytecorto: System.Int16e così via

Ora la domanda da un milione di dollari dal punto di vista del programmatore Quindi quando usare "String" e "string"?

Per prima cosa, per evitare confusione, usarne una in modo coerente. Ma dal punto di vista delle migliori pratiche quando si fa una dichiarazione variabile è bene usare "string" (piccole "s") e quando lo si utilizza come nome di classe, si preferisce "String" (maiuscola "S").

Nel codice sottostante il lato sinistro è una dichiarazione variabile e dichiarata usando "stringa". Sul lato destro stiamo chiamando un metodo, quindi "String" è più sensato.

string s = String.ToUpper() ;

25
"In breve" String "è un alias (la stessa cosa chiamata con nomi diversi) di" stringa "". Questo non è corretto: l'alias è "stringa".
Xavier Egea,

3
quando fai una dichiarazione variabile è bene usare "string" (piccole "s") e quando lo usi come nome di classe, allora è preferibile "String" (maiuscola "S"). Questa convenzione sembra non essere più valida: se usi Visual Studio 2015 e provi a scriverti Stringti suggerisco di "semplificare il tuo codice", portandolo a string...
Massimiliano Kraus

166

Le lettere minuscole stringsono un alias per System.String. Sono gli stessi dentro C#.

C'è un dibattito sul fatto che si dovrebbe utilizzare i tipi di sistema ( System.Int32, System.String, ecc) tipi o la C# aliases( int, string, ecc). Personalmente credo che dovresti usare il C# aliases, ma questa è solo la mia preferenza personale.


4
Questo è il problema, non sono alias 'C #', sono alias 'C'. Non c'è "stringa" nativa o "int" nel linguaggio C #, ma solo zucchero sintattico.
Quarkly,

16
non sono sicuro da dove provenga "C", poiché la specifica del linguaggio C # 5 riporta "La stringa di parole chiave è semplicemente un alias per la classe predefinita System.String." a pagina 85, paragrafo 4.2.4. Tutte le lingue di alto livello sono zucchero sintattico su set di istruzioni della CPU e bytecode.
aiodintsov,

157

stringè solo un alias per System.String. Il compilatore li tratterà in modo identico.

L'unica differenza pratica è l'evidenziazione della sintassi mentre menzioni e che devi scrivere using Systemse lo usi String.


Non è necessario aggiungere il prefisso System per utilizzare String.
Joe Ratzer,

18
È necessario includere un using Systemquando si utilizza String, altrimenti si ottiene il seguente errore:The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
Ronald

144

Entrambi sono uguali. Ma dal punto di vista delle linee guida di codifica è meglio usare stringinvece di String. Questo è ciò che generalmente usano gli sviluppatori. ad es. invece di usare Int32usiamo intcome intè alias aInt32

Cordiali saluti "La stringa di parole chiave è semplicemente un alias per la classe predefinita System.String." - Specifica del linguaggio C # 4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx


121

Come dicono gli altri, sono gli stessi. Regole StyleCop, per impostazione predefinita, faranno rispettare l'utilizzo di stringun codice di stile C # migliori pratiche, ad eccezione di quando si fa riferimento System.Stringfunzioni statiche, ad esempio String.Format, String.Join, String.Concat, ecc ...


4
Non sapevo che StyleCop avrebbe contrassegnato l'uso di String, ad eccezione dei metodi statici. Penso che sia fantastico in quanto è come lo uso sempre: stringa per le dichiarazioni di tipo e stringa quando accedo ai membri statici.
Goyuix,

102

Nuova risposta dopo 6 anni e 5 mesi (procrastinazione).

Mentre stringè una parola chiave riservata C # che ha sempre un significato fisso, Stringè solo un identificatore ordinario che potrebbe riferirsi a qualsiasi cosa. A seconda dei membri del tipo corrente, lo spazio dei nomi corrente e le usingdirettive applicate e il loro posizionamento Stringpotrebbero essere un valore o un tipo distinti da global::System.String.

Fornirò due esempi in cui le usingdirettive non aiuteranno .


Innanzitutto, quando Stringè un valore del tipo corrente (o una variabile locale):

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

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

Quanto sopra non verrà compilato perché IEnumerable<>non ha un membro non statico chiamato Formate non si applicano metodi di estensione. Nel caso precedente, potrebbe essere ancora possibile utilizzare Stringin altri contesti in cui un tipo è l'unica possibilità sintatticamente. Ad esempio, String local = "Hi mum!";potrebbe essere OK (a seconda dello spazio dei nomi e delle usingdirettive).

Peggio ancora: dire String.Concat(someSequence)che probabilmente (a seconda dei using) andrà al metodo di estensione Linq Enumerable.Concat. Non andrà al metodo statico string.Concat.


In secondo luogo, quando Stringè un altro tipo , nidificato all'interno del tipo corrente:

class MyPiano
{
  protected class String
  {
  }

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

Nessuna delle istruzioni nel Examplemetodo viene compilata. Qui Stringè sempre un pianoforte archi , MyPiano.String. Nessun membro ( statico no) Formatesiste (o è ereditato dalla sua classe base). E il valore "Goodbye"non può essere convertito in esso.


4
Suppongo che si possa essere diabolici: using String = System.Int32; using Int32 = System.String; e poi contare i bug.
Steve,

7
Questa è la risposta esatta. stringlo è System.String. Stringpotrebbe essere qualsiasi cosa.
Dave Cousineau,

Concordato @DaveCousineau - questo è il punto dell'alias. È possibile creare un altro Stringtipo che non verrebbe impostato sull'oggetto System.String. Check out: blog.paranoidcoding.com/2019/04/08/…
Kristopher

"La parola chiave stringha un significato concreto in C #. È il tipo System.Stringesistente nell'assemblaggio di runtime principale. Il runtime comprende intrinsecamente questo tipo e fornisce le funzionalità che gli sviluppatori si aspettano stringsin .NET. La sua presenza è così critica per C # che se quel tipo non lo fa esiste che il compilatore uscirà prima di tentare persino di analizzare una riga di codice. Quindi stringha un significato preciso e inequivocabile nel codice C #. L'identificatore Stringsebbene non abbia un significato concreto in C #. È un identificatore che passa attraverso tutte le regole di ricerca del nome come Widget, Studentecc ... "
Kristopher,



88

Contro quello che sembra essere una pratica comune tra gli altri programmatori, preferisco Stringsopra string, solo per evidenziare il fatto che Stringè un tipo di riferimento, come detto Jon Skeet.



78

Vorrei solo aggiungere questo alla risposta di lfousts, dal libro di Ritchers:

La specifica del linguaggio C # afferma: "Per motivi di stile, l'uso della parola chiave è preferito rispetto all'uso del nome completo del tipo di sistema". Non sono d'accordo con le specifiche del linguaggio; Preferisco usare i nomi dei tipi FCL ed evitare completamente i nomi dei tipi primitivi. In realtà, vorrei che i compilatori non offrissero nemmeno i nomi dei tipi primitivi e costringessero gli sviluppatori a usare i nomi dei tipi FCL. Ecco i miei motivi:

  • Ho visto diversi sviluppatori confusi, non sapendo se usare la stringa o la stringa nel loro codice. Perché nella stringa C # (una parola chiave) si associa esattamente a System.String (un tipo FCL), non vi è alcuna differenza ed è possibile utilizzare entrambi. Allo stesso modo, ho sentito alcuni sviluppatori dire che int rappresenta un numero intero a 32 bit quando l'applicazione è in esecuzione su un sistema operativo a 32 bit e che rappresenta un numero intero a 64 bit quando l'applicazione è in esecuzione su un sistema operativo a 64 bit. Questa affermazione è assolutamente falsa: in C #, un int è sempre mappato a System.Int32 e quindi rappresenta un numero intero a 32 bit indipendentemente dal sistema operativo su cui è in esecuzione il codice. Se i programmatori avrebbero usatoInt32 nel loro codice, quindi anche questa potenziale confusione viene eliminata.

  • In C #, long esegue il mapping a System.Int64 , ma in un linguaggio di programmazione diverso, long può eseguire il mapping a Int16 o Int32 . Infatti, C ++ / CLI fa piacere lungo come Int32 . Qualcuno che legge il codice sorgente in una lingua potrebbe facilmente interpretare male l'intenzione del codice se fosse abituato a programmare in un linguaggio di programmazione diverso. In effetti, la maggior parte delle lingue non tratterà nemmeno a lungo come una parola chiave e non compilerà il codice che la utilizza.

  • La FCL ha molti metodi che hanno nomi di tipi come parte dei loro nomi di metodi. Ad esempio, il tipo BinaryReader offre metodi come ReadBoolean , ReadInt32 , ReadSingle e così via, mentre il tipo System.Convert offre metodi come ToBoolean , ToInt32 , ToSingle e così via. Sebbene sia legale scrivere il seguente codice, la riga con float mi sembra molto innaturale e non è ovvio che la riga sia corretta:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • Molti programmatori che usano C # tendono esclusivamente a dimenticare che altri linguaggi di programmazione possono essere usati contro il CLR, e per questo motivo i meccanismi C # si insinuano nel codice della libreria di classi. Ad esempio, FCL di Microsoft è quasi scritto esclusivamente in C # e sviluppatori del team di FCL hanno introdotto metodi nella libreria, come Array ‘s GetLongLength , che restituisce un Int64 valore che è un lungo in C #, ma non in altre lingue (come il C ++ / CLI). Un altro esempio è System.Linq.Enumerable s’ LongCount metodo.

Non ho ottenuto la sua opinione prima di leggere il paragrafo completo.


72

String ( System.String) è una classe nella libreria di classi base. string (in minuscolo) è un lavoro riservato in C # che è un alias per System.String. Int32 vs int è una situazione simile com'è Boolean vs. bool. Queste parole chiave specifiche del linguaggio C # ti consentono di dichiarare le primitive in uno stile simile a C.


67

Stringnon è una parola chiave e può essere utilizzata come identificatore, mentre stringè una parola chiave e non può essere utilizzata come identificatore. E dal punto di vista funzionale entrambi sono uguali.


67

È una questione di convenzioni, davvero. stringassomiglia di più allo stile C / C ++. La convenzione generale consiste nell'utilizzare qualsiasi scorciatoia fornita dalla lingua scelta (int / Int Int32). Questo vale per "oggetto" e decimalpure.

Teoricamente questo potrebbe aiutare a convertire il codice in un futuro standard a 64 bit in cui "int" potrebbe significare Int64, ma non è questo il punto, e mi aspetterei che qualsiasi procedura guidata di aggiornamento cambi comunque qualsiasi intriferimento Int32solo per sicurezza.


66

Venire tardi alla festa: uso i tipi CLR il 100% delle volte (beh, tranne se costretto a usare il tipo C #, ma non ricordo quando è stata l'ultima volta).

Inizialmente ho iniziato a farlo anni fa, secondo i libri CLR di Ritchie. Per me aveva senso che tutti i linguaggi CLR alla fine dovessero essere in grado di supportare l'insieme dei tipi CLR, quindi l'uso dei tipi CLR da soli fornito codice più chiaro e forse più "riutilizzabile".

Ora che lo faccio da anni, è un'abitudine e mi piace la colorazione che VS mostra per i tipi CLR.

L'unico aspetto negativo è che il completamento automatico utilizza il tipo C #, quindi finisco per riscrivere i tipi generati automaticamente per specificare il tipo CLR.

Inoltre, ora, quando vedo "int" o "string", mi sembra davvero sbagliato, come se stessi guardando il codice C degli anni '70.


49

Non c'è differenza.

La parola chiave C # si stringassocia al tipo .NET System.String: è un alias che mantiene le convenzioni di denominazione del linguaggio.

Allo stesso modo, intmappa a System.Int32.


In una build a 64 bit, int esegue il mapping a System.Int64 (8 byte), in 32 bit lo esegue il mapping a System.Int32 (4 byte)
Alex

1
IntPtr e UIntPtr sono gli unici tipi che cambiano dimensione in base alla piattaforma (ignorando i tipi di puntatore effettivi come int*e i tipi composti da [U] IntPtrs o puntatori effettivi).
P Daddy,

45

C'è una citazione su questo numero dal libro di Daniel Solis .

Tutti i tipi predefiniti sono associati direttamente ai tipi .NET sottostanti. I nomi dei tipi C # (stringa) sono semplicemente alias per i tipi .NET (String o System.String), quindi l'utilizzo dei nomi .NET funziona in modo sintattico, sebbene questo sia scoraggiato. All'interno di un programma C #, è necessario utilizzare i nomi C # anziché i nomi .NET.


41

stringa è una parola chiave e non è possibile utilizzare la stringa come identificatore.

String non è una parola chiave e puoi usarla come identificatore:

Esempio

string String = "I am a string";

La parola chiave string è un alias a System.Stringparte il problema della parola chiave, i due sono esattamente equivalenti.

 typeof(string) == typeof(String) == typeof(System.String)

2
L'unica piccola differenza è che se usi la classe String, devi importare lo spazio dei nomi di sistema in cima al tuo file, mentre non devi farlo quando usi la parola chiave string.
Uttam,

Ci sono semplici casi d'uso in cui l'istruzione di uguaglianza fallirebbe ... Come definire una stringa di tipo call nello spazio dei nomi blah e importare quello spazio di nomi nel file in cui è in esecuzione l'istruzione di uguaglianza.
Rick

40

Sì, non c'è alcuna differenza tra loro, proprio come il boole Boolean.


40

@JaredPar (uno sviluppatore del compilatore C # e un prolifico utente SO!) Ha scritto un ottimo post sul blog su questo problema. Penso che valga la pena condividere qui. È una bella prospettiva sul nostro argomento.

stringvs. Stringnon è un dibattito di stile

[...]

La parola chiave stringha un significato concreto in C #. È il tipo System.Stringesistente nell'assemblaggio di runtime principale. Il runtime comprende intrinsecamente questo tipo e fornisce le funzionalità che gli sviluppatori si aspettano per le stringhe in .NET. La sua presenza è così critica per C # che se quel tipo non esiste il compilatore uscirà prima di tentare persino di analizzare una riga di codice. Quindi stringha un significato preciso e inequivocabile nel codice C #.

L'identificatore, Stringtuttavia, non ha alcun significato concreto in C #. È un identificatore che passa attraverso tutte le regole di ricerca del nome come Widget, Studentecc. Potrebbe legarsi alla stringa o potrebbe legarsi a un tipo in un altro assieme i cui scopi potrebbero essere completamente diversi da string. Peggio ancora, potrebbe essere definito in modo tale che il codice piaccia String s = "hello"; ha continuato a compilare.

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;
}

Il significato effettivo di Stringdipenderà sempre dalla risoluzione dei nomi. Ciò significa che dipende da tutti i file di origine nel progetto e da tutti i tipi definiti in tutti gli assiemi di riferimento. In breve, richiede un po 'di contesto per sapere cosa significa.

È vero che nella stragrande maggioranza dei casi Stringe stringsi legherà allo stesso tipo. Ma usare Stringsignifica ancora che gli sviluppatori stanno lasciando il loro programma all'interpretazione in luoghi in cui esiste una sola risposta corretta. Quando Stringsi lega al tipo sbagliato, può lasciare agli sviluppatori il debug per ore, archiviare bug nel team del compilatore e in generale perdere tempo che avrebbe potuto essere salvato utilizzando string.

Un altro modo per visualizzare la differenza è con questo esempio:

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

Molti sosterranno che, sebbene queste informazioni siano tecnicamente accurate, l'uso Stringè ancora valido perché è estremamente raro che una base di codice definisca un tipo di questo nome. O che quando Stringè definito è un segno di una base di codice errata.

[...]

Vedrai che Stringè definito per una serie di scopi completamente validi: aiutanti di riflessione, librerie di serializzazione, lexer, protocolli, ecc ... Per ognuna di queste librerie Stringvs. stringha conseguenze reali a seconda di dove viene usato il codice.

Quindi ricorda quando vedi il dibattito Stringvs. stringquesto riguarda la semantica, non lo stile. La scelta della stringa dà un significato nitido alla base di codice. Scegliere Stringnon è sbagliato ma sta lasciando la porta aperta alle sorprese in futuro.

Nota: ho copiato / incollato la maggior parte del post del blog per motivi di archiviazione. Ignoro alcune parti, quindi consiglio di saltare e leggere il post del blog, se puoi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.