Quelle est la différence entre String et string en C #?


6514

Exemple ( notez le cas ):

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

Quelles sont les directives pour l'utilisation de chacun? Et quelles sont les différences?


72
@ORMapper, mais le fait demeure qu'il strings'agit d'une construction lexicale de la grammaire C # alors qu'il ne System.Strings'agit que d'un type. Indépendamment de toute différence explicite mentionnée dans une spécification, il y a toujours cette différence implicite qui pourrait être acceptée avec une certaine ambiguïté. Le langage lui-même doit prendre stringen charge d'une manière que l'implémentation n'est pas (tout à fait) obligée de considérer pour une classe particulière dans la BCL.
Kirk Woll,

106
@KirkWoll: Selon la spécification du langage, le langage lui-même doit considérer stringêtre exactement le même que le type BCL System.String, rien d'autre. Ce n'est pas du tout ambigu. Bien sûr, vous pouvez implémenter votre propre compilateur, en utilisant la grammaire C #, et utiliser tous les jetons trouvés comme ça pour quelque chose d'arbitraire, sans rapport avec ce qui est défini dans la spécification du langage C #. Cependant, le langage résultant ne serait qu'un sosie C #, il ne pouvait pas être considéré comme C #.
OR Mapper

88
Vous pouvez utiliser stringsans directive using pour System. Vous ne pouvez pas faire ça avec String.
Wilsu

14
Pour quelqu'un qui vient d'Algol et de Fortran, cette discussion montre qu'il y a quelque chose qui ne va pas string. Il est nécessaire de l'abréger System.String, mais, en tant qu'alias, il semble tout à fait, mais pas exactement la même chose. Après plusieurs années de C #, bien que, je dirais, il est sûr d'utiliser simplement stringet string.Format()et pas à vous soucier System.String.
Roland

8
@Sangeeta Que dites-vous? La System.Stringclasse est toujours là et le stringmot-clé en est toujours un alias. Tout comme System.Int32et int. Ils sont littéralement la même chose.
Craig

Réponses:


6107

stringest un alias en C # pour System.String.
Donc techniquement, il n'y a pas de différence. C'est comme int contre System.Int32 .

En ce qui concerne les directives, il est généralement recommandé d'utiliser stringchaque fois que vous faites référence à un objet.

par exemple

string place = "world";

De même, je pense qu'il est généralement recommandé d'utiliser Stringsi vous devez vous référer spécifiquement à la classe.

par exemple

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

C'est le style que Microsoft a tendance à utiliser dans ses exemples .

Il semble que les conseils dans ce domaine peuvent avoir changé, car StyleCop impose désormais l'utilisation des alias spécifiques à C #.


163
Si vous décidez d'utiliser StyleCop et suivez cela, cela signifie d'utiliser les types spécifiques à la langue. Donc pour C #, vous aurez string (au lieu de String), int (au lieu de Int32), float (au lieu de Single) - stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz

144
J'utilise toujours les alias parce que j'ai supposé qu'un jour cela pourrait être utile car ils agissent comme une abstraction, donc leur implémentation peut donc être modifiée sans que j'aie à le savoir.
Rob

37
Visual Studio 2015 dit que String.Format devrait être changé en string.Format, donc je suppose que Microsoft va dans ce sens. J'ai également toujours utilisé String pour les méthodes statiques.
Sami Kuhmonen

32
En les lisant, j'ai remarqué que plusieurs des commentaires étaient tout simplement incorrects. @ DRAirey1 Avec le temps, vous constaterez que l'ancienne méthode est toujours la meilleure, si vous en doutez, je vous mets au défi d'essayer d'écrire du code C # sans utiliser Visual Studio. C'est pratiquement impossible et une situation qui survient de temps en temps dans le travail de développement Web. @Vlad Vous n'avez pas besoin d'importer quoi que ce soit pour utiliser String. @Abhi Votre commentaire est inutile et tout aussi vrai pour string.Format(). @KlitosG Non, ce n'est pas vrai. Ils fonctionnent tous exactement de la même manière.
krowe2

46
Pourriez-vous ajouter une remarque qu'il y a, en fait, une différence? Par exemple: nameof(string)ne compilera pas alors que le nameof(String)sera.
Jeroen Vannevel

3441

Juste pour être complet, voici une décharge de cerveau d'informations connexes ...

Comme d'autres l'ont noté, stringest un alias pour System.String. Ils compilent dans le même code, donc au moment de l'exécution, il n'y a aucune différence. Ce n'est qu'un des alias en C #. La liste complète est:

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

Mis à part stringet object, les alias sont tous des types de valeur. decimalest un type de valeur, mais pas un type primitif dans le CLR. Le seul type primitif qui n'a pas d'alias est System.IntPtr.

Dans la spécification, les alias de type valeur sont appelés «types simples». Les littéraux peuvent être utilisés pour des valeurs constantes de chaque type simple; aucun autre type de valeur n'a de formes littérales disponibles. (Comparez cela avec VB, qui autorise les DateTimelittéraux et a aussi un alias.)

Il existe une circonstance dans laquelle vous devez utiliser les alias: lors de la spécification explicite du type sous-jacent d'une énumération. Par exemple:

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

C'est juste une question de la façon dont les spécifications définit les Déclarations ENUM - la partie après le côlon doit être le type intégré de production, ce qui est un signe de sbyte, byte, short, ushort, int, uint, long, ulong, char... par opposition à un genre production utilisé par les déclarations de variables par exemple. Cela n'indique aucune autre différence.

Enfin, en ce qui concerne l'utilisation: personnellement, j'utilise les alias partout pour l'implémentation, mais le type CLR pour toutes les API. Peu importe vraiment ce que vous utilisez en termes d'implémentation - la cohérence au sein de votre équipe est agréable, mais personne d'autre ne s'en souciera. D'un autre côté, il est vraiment important que si vous vous référez à un type dans une API, vous le faites d'une manière indépendante de la langue. Une méthode appelée ReadInt32n'est pas ambiguë, tandis qu'une méthode appelée ReadIntnécessite une interprétation. L'appelant pourrait utiliser une langue qui définit un intalias pour Int16, par exemple. Les concepteurs du framework .NET ont suivi ce modèle, de bons exemples étant dans les BitConverter, BinaryReaderet les Convertclasses.


82
La situation de succession avec enum est intéressante. Pouvez-vous indiquer la documentation expliquant pourquoi l'alias doit être utilisé pour les énumérations? Ou est-ce un bug connu?
JaredPar

149
C'est dans la section 14.1 de la spécification (je ne peux pas citer facilement car c'est trop long). Cela ne dit pas explicitement que vous devez utiliser l'alias, mais les alias sont en quelque sorte traités comme leurs propres types. C'est un peu bizarre.
Jon Skeet

32
@PiPeep, ce qui est plus étonnant que le grand nombre de votes positifs, c'est le nombre incroyablement bas de votes négatifs (considérez que les 5 premiers messages ont un total de plus de 2000 votes positifs, et pourtant seulement 1 vote négatif parmi eux tous). Surtout quand vous tenez compte de la notion qu'il y a toujours des «haineux» dans n'importe quelle communauté, je trouve cela tout simplement incroyable.
corsiKa

40
Une différence intéressante entre stringet Stringest que 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"; `est acceptable, tout comme Stringun identifire et non un mot-clé.
Sanjeev Rai

33
@SanjeevRai: Oui. Vous pouvez utiliser @stringpour créer un identifiant qui se termine comme stringsi. C'est une sorte de mécanisme d'échappement.
Jon Skeet

716

Stringreprésente System.Stringet c'est un type .NET Framework. stringest un alias en langage C # pour System.String. Les deux sont compilés System.Stringen IL (Intermediate Language), il n'y a donc pas de différence. Choisissez ce que vous aimez et utilisez-le. Si vous codez en C #, je préfère stringcar c'est un alias de type C # et bien connu des programmeurs C #.

Je peux en dire autant de ( int, System.Int32) etc.


3
`Si vous codez en C #, je préférerais une chaîne car c'est un alias de type C # et bien connu des programmeurs C # - quand une personne C # ne connaîtrait-elle pas le framework .NET. +1 car je pense que c'est généralement la meilleure réponse, mais le point que je mentionne semble étrange.
MyDaftQuestions

4
Personnellement, je préfère utiliser "Int32", car il montre immédiatement la plage de la valeur. Imaginez s'ils ont mis à niveau le type de "int" sur les systèmes à bits supérieurs ultérieurs. 'int' en c est apparemment considéré comme "le type entier avec lequel le processeur cible travaille le plus efficacement" , et défini comme "au moins 16 bits". Je préfère une cohérence prévisible là-bas, merci beaucoup.
Nyerguds

2
@MyDaftQuestions Je suis d'accord. Si quoi que ce soit, il serait logique d' utiliser systématiquement les types .net car ils ignorent la langue et le type est évident, indépendant de toute langue (est-ce que je connais toutes les idiosyncrasies de F # ou de VB?).
Peter - Rétablir Monica le

5
@Nyerguds Il y a deux raisons de ne pas s'en inquiéter. L'une est intdéfinie dans la spécification du langage C # comme un entier 32 bits, quel que soit le matériel. C #, malgré un héritage partagé dans la nuit des temps, n'est pas en fait C. Changer intpour un entier 64 bits serait un changement de rupture dans la spécification et le langage. Il faudrait également redéfinir long, comme longc'est actuellement l'entier 64 bits. L'autre raison de ne pas s'inquiéter n'est pas pertinente car les types ne changeront jamais, mais .NET est juste assez abstrait pour que 99% du temps vous n'ayez pas à y penser de toute façon. ;-)
Craig

5
@Craig Je fouille dans de nombreux anciens formats de jeu propriétaires où je dois y penser tout le temps, cependant. Et puis en utilisant Int16, Int32et Int64c'est beaucoup plus transparent dans le code qu'en utilisant le plutôt non descriptif short, intetlong
Nyerguds

506

La meilleure réponse que j'ai jamais entendu parler de l'utilisation des alias de type fournis en C # vient de Jeffrey Richter dans son livre CLR Via C # . Voici ses 3 raisons:

  • J'ai vu un certain nombre de développeurs confus, ne sachant pas s'il fallait utiliser chaîne ou une chaîne dans leur code. Parce qu'en C # la chaîne (un mot-clé) correspond exactement à System.String (un type FCL), il n'y a pas de différence et l'une ou l'autre peut être utilisée.
  • En C #, les mappages longs vers System.Int64 , mais dans un langage de programmation différent, long peuvent mapper vers un Int16 ou Int32 . En fait, C ++ / CLI traite en fait longtemps comme un Int32 . Quelqu'un qui lit le code source dans une langue pourrait facilement mal interpréter l'intention du code s'il était habitué à programmer dans un autre langage de programmation. En fait, la plupart des langues ne traiteront même pas longtemps comme un mot-clé et ne compileront pas le code qui l'utilise.
  • Le FCL possède de nombreuses méthodes dont les noms de type font partie de leurs noms de méthode. Par exemple, le type BinaryReader propose des méthodes telles que ReadBoolean , ReadInt32 , ReadSingle , etc. Le type System.Convert propose des méthodes telles que ToBoolean , ToInt32 , ToSingle , etc. Bien qu'il soit légal d'écrire le code suivant, la ligne avec float me semble très peu naturelle, et il n'est pas évident que la ligne soit correcte:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Alors voilà. Je pense que ce sont tous de très bons points. Cependant, je ne me retrouve pas à utiliser les conseils de Jeffrey dans mon propre code. Peut-être que je suis trop coincé dans mon monde C # mais je finis par essayer de faire ressembler mon code au code framework.


24
Le deuxième point ressemble en fait à une raison de ne pas utiliser string, intetc.
MauganRa

15
@MauganRa Et c'est censé le faire, l'auteur du livre énumère les raisons pour lesquelles il n'utilise pas d' alias.
tomi.lee.jones

31
"Si quelqu'un lit le code source C #, il doit interpréter longtemps en fonction de la spécification de langue, et non d'une autre spécification de langue." Cela manque complètement le point. Ce n'est pas que quelqu'un ait l' intention de mal interpréter le code, il est simplement facile pour son cerveau de sauter à la mauvaise conclusion lorsqu'un type a une signification différente de celle que le programmeur voit quotidiennement dans un autre contexte. Nous faisons tous des erreurs; l'utilisation de types nommés explicitement rend ces erreurs moins probables.
Darryl

10
+ Ces raisons résument mes sentiments à ce sujet. Lorsque j'ai commencé à coder en C # (provenant d'un arrière-plan Java / C ++ / C), je pensais que les alias étaient laids. Je pense toujours de cette façon, malheureusement la plupart du monde ne semble pas être d'accord avec moi, ou ils s'en moquent, alors utilisez les minuscules.
gusgorman

8
@jinzai, la question porte sur C #, dans lequel longest défini comme un entier signé 64 bits, quelle que soit la plateforme ou le compilateur. Ainsi , dans certains cas au moins, oui, il ne dépend de la langue.
phoog

456

string est un mot réservé, mais String n'est qu'un nom de classe. Cela signifie qu'il stringne peut pas être utilisé seul comme nom de variable.

Si, pour une raison quelconque, vous vouliez une variable appelée chaîne , vous ne verriez que la première de ces compilations:

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

Si vous voulez vraiment un nom de variable appelé chaîne, vous pouvez l'utiliser @comme préfixe:

StringBuilder @string = new StringBuilder();

Autre différence critique: Stack Overflow les met en évidence différemment.


20
Gardez à l'esprit que l'appel d'un local @stringest vraiment inutile, car les noms des locaux ne sont présents que dans les PDB. Autant l'appeler _stringou quelque chose comme ça. Cela a plus de sens pour les choses dont les noms sont accessibles via la réflexion, où @stringserait le nom d'un membre "string".
Roman Starkov

25
Gardez également à l'esprit que l'utilisation d'un mot réservé comme nom de variable est extrêmement inélégante.
Elton

7
L'OP ne souhaite pas utiliser String ou string comme nom de variable. Ils ont demandé une explication de la différence entre ces types . Votre réponse ne fait qu'ajouter de la confusion IMO
Matt Wilko

1
@craig si vous écriviez un logiciel pour apprendre aux gens à faire des nœuds?
Simon_Weaver

5
@Simon_Weaver noeuds dans les chaînes? haha, chouette. :-) Bien sûr, vous pouvez choisir un autre nom, comme thread. Attends une minute ... D'oh!
Craig

392

Il y a une différence - vous ne pouvez pas utiliser Stringsans using System;au préalable.


14
par défaut, la plupart des gens l'ajoutent de quelque manière que ce soit en haut du fichier. VS le fait par défaut dans la plupart des cas, pas tous!
IbrarMumtaz

9
Par défaut, j'ajoute uniquement les usinginstructions dont j'ai besoin et je supprime explicitement tout ce que je n'ai pas. Power Productivity Tools> "[x] Supprimer et formater les utilisations lors de l'enregistrement"
JMD

2
@JMD J'ai modifié le fichier de modèle .cs pour qu'il ne contienne même aucune instruction using en haut! J'ai également changé le modèle de classe en internal sealed.
ErikE

@JMD Je déteste cette fonctionnalité. Il effectue parfois des modifications sur des fichiers par ailleurs intacts, ce qui rend difficile de voir les modifications réelles contenues dans un ensemble de modifications. Bien sûr, je supprime généralement "l'utilisation du spam", mais seulement activement, pas automatiquement.
mg30rg

Cela peut être le cas pour C #, mais pas pour tous les langages .NET. (Powershell importe l'espace de noms System par défaut.)
FSCKur

312

Il a été couvert ci-dessus; cependant, vous ne pouvez pas l'utiliser stringen réflexion; vous devez utiliser String.


6
Je ne comprends pas ce que signifie cette réponse et pourquoi elle a été votée positivement. Vous pouvez utiliser typeof(string)en réflexion. Exemple un: if (someMethodInfo.ReturnType == typeof(string)) { ... }Exemple deux: var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);Où devez-vous utiliser String, non string? Si vous essayez des choses comme Type.GetType("String")ou Type.GetType("string"), aucune ne trouvera la classe car l'espace de noms est manquant. Si pour une raison stupide vous comparez .Named'un type à "string"d'une manière sensible à la casse, vous avez raison.
Jeppe Stig Nielsen

257

System.Stringest la classe de chaîne .NET - en C # stringest un alias pourSystem.String - donc à l'usage elles sont les mêmes.

En ce qui concerne les directives, je ne serais pas trop embourbé et j'utiliserais simplement ce que vous ressentez - il y a des choses plus importantes dans la vie et le code sera de toute façon le même.

Si vous trouvez - vous des systèmes de construction où il est nécessaire de préciser la taille des entiers que vous utilisez et ainsi tendance à utiliser Int16, Int32, UInt16, UInt32etc. , alors il peut sembler plus naturel d'utiliser String- et lorsqu'ils se déplacent entre les différentes langues de .net , il pourrait rendre les choses plus compréhensibles - sinon j'utiliserais string et int.


2
Choisissez-en un et soyez cohérent. Si vous travaillez quelque part avec un style maison, utilisez-le.
Alan B

3
malheureusement, le style est une préférence personnelle et peut être trop coûteux à appliquer dans une large base de code à travers plusieurs équipes sans propriétaire de code dédié. il y a toujours des questions plus importantes à prendre en charge plutôt que chaîne contre chaîne. ce qui nous ramène à "des choses plus importantes dans la vie"
aiodintsov

C'est définitivement une préférence; par exemple: Je préfère utiliser short, int, ushort, au uintlieu de Int16, etc. La plupart du temps parce que c'est que j'ai appris. Certes, il Int16est plus facile de comprendre immédiatement pour ceux qui ont moins d'expérience. +1 De moi!
Candleshark

211

Je préfère les .NETtypes en majuscules (plutôt que les alias) pour des raisons de formatage. Les .NETtypes sont colorés de la même manière que les autres types d'objet (les types de valeur sont des objets appropriés, après tout).

Mots - clés conditionnel et de contrôle (comme if, switch, etreturn ) sont en minuscules et de couleur bleu foncé (par défaut). Et je préfère ne pas avoir le désaccord sur l'utilisation et le format.

Considérer:

String someString; 
string anotherString; 

11
Écrivez-vous également du code comme: Int32 i = 1; Plutôt que int i = 1; ? Semble incohérent de ne pas utiliser l'alias de chaîne lorsqu'il est disponible.
bytedev

29
@nashwan: en fait, oui, j'utilise Int32 i=1;plutôt que int i = 1; je trouve le premier plus lisible quant à mon intention: à savoir que je veux un entier signé 32 bits.
NotMe

5
Eh bien, je suppose que tout dépend si le développeur pense qu'il écrit du code C # (chaîne) ou du code .NET (chaîne). Personnellement, je pense avant tout que j'écris en C # (et c'est C # qui utilise .NET).
bytedev

7
@Alex: mon argument était simplement que je préfère être très précis dans mon codage afin de lever toute ambiguïté.
NotMe

22
À l'autre extrémité du spectre, j'utilise presque toujoursvar
tic

193

stringet Stringsont identiques à tous égards (sauf le "S" majuscule). Il n'y a aucune incidence sur les performances dans les deux cas.

Les minuscules stringsont préférées dans la plupart des projets en raison de la coloration syntaxique


Jeffrey Richter recommande d'utiliser le type CLR dans tous les cas (CLR via C #) pour éviter exactement le genre de confusion qui se produit ici.
Josh

De toute évidence, que vous utilisiez S ou S, cela aura causé ces questions, alors votez pour Richter. ;)
Brad Wilson

Richter voulait dire que la chaîne n'aurait pas dû être une option - Microsoft ne devrait pas l'avoir dans la langue. Vous ne pouvez pas voter contre Richter - c'est une légende! :)
Joe Ratzer

1
Je suis d'accord qu'il aurait peut- être été préférable de ne pas avoir d'alias du tout. Mais étant donné que nous les avons, je pense que c'est bien de les utiliser (mais pas dans les noms de méthode, etc.)
Jon Skeet

10
"chaîne" n'est pas la même chose que "chaîne". Est signifie "System.String". Donc, si vous utilisez "String", vous devez mettre "using System" pour inclure l'espace de noms
ThiagoAlves

186

C # est un langage utilisé avec le CLR.

string est un type en C #.

System.String est un type du CLR.

Lorsque vous utilisez C # avec le CLR stringsera mappé System.String.

Théoriquement, vous pouvez implémenter un compilateur C # qui génère un bytecode Java. Une mise en œuvre judicieuse de ce compilateur carte probablement stringà java.lang.Stringpour interopérer avec la bibliothèque d'exécution Java.


1
stringn'est pas un type en C #; c'est un mot réservé qui correspond à un type du CLR.
CesarGon

@CesarGon: Selon ECMA-334, section 8.2.1: "C # fournit un ensemble de types prédéfinis [...] Les types de référence prédéfinis sont objet et chaîne."
Rasmus Faber

10
Selon ECMA-334, section 9.4.3, "chaîne" est un mot-clé. :-) Je suis d'accord avec vous que "chaîne" est un type si vous vous concentrez sur la sémantique, mais je dirais que c'est un mot-clé (c'est-à-dire un mot réservé) si vous vous concentrez sur la syntaxe. La norme soutient les deux points de vue (peut-être trop ambiguë!). Pour moi, l'OP concerne la syntaxe, j'ai donc tendance à me concentrer sur la syntaxe lorsque je regarde les réponses, mais je vois aussi votre point. De plus, votre réponse, telle qu'elle est, peut être interprétée comme signifiant qu'il existe deux types différents: string et String, lorsque ce n'est pas le cas. L'un correspond à l'autre.
CesarGon

Soyons clairs à ce sujet. 'chaîne' est un alias réservé. Ce n'est pas un vrai type de données. C'est quelque chose qui pointe vers autre chose. Vous pouvez supprimer tous ces alias (ou simplement ne jamais les utiliser) et disposer d'un langage de programmation parfaitement adapté.
Quarkly

169

Cette vidéo YouTube montre pratiquement en quoi ils diffèrent.

Mais maintenant, pour une longue réponse textuelle.

Lorsque nous parlons de .NETdeux choses différentes, l'une est un .NETframework et l'autre il y a des langages ( C#, VB.NETetc.) qui utilisent ce framework.

entrez la description de l'image ici

" System.String" aka "String" (majuscule "S") est un .NETtype de données de framework tandis que "string" est un C#type de données.

entrez la description de l'image ici

En bref, "String" est un alias (la même chose appelée avec des noms différents) de "string". Donc, techniquement, les deux instructions de code ci-dessous donneront la même sortie.

String s = "I am String";

ou

string s = "I am String";

De la même manière, il existe des alias pour d'autres types de données c # comme indiqué ci-dessous: -

objet: System.Object, string: System.String, bool: System.Booleanoctet: System.Byte, sbyte: System.SBytecourt: System.Int16et ainsi de suite

Maintenant, la question à un million de dollars du point de vue du programmeur. Alors, quand utiliser "String" et "string"?

Première chose pour éviter la confusion, utilisez l'un d'eux de manière cohérente. Mais du point de vue des meilleures pratiques, lorsque vous faites une déclaration de variable, il est bon d'utiliser "string" (petit "s") et lorsque vous l'utilisez comme nom de classe, "String" (majuscule "S") est préférable.

Dans le code ci-dessous, le côté gauche est une déclaration de variable et il a déclaré en utilisant "chaîne". A droite, nous appelons une méthode, donc "String" est plus sensé.

string s = String.ToUpper() ;

25
"En bref" String "est un alias (la même chose appelée avec des noms différents) de" string "". Ce n'est pas correct: l'alias est "string".
Xavier Egea

3
lorsque vous faites une déclaration de variable, il est bon d'utiliser "string" (petit "s") et lorsque vous l'utilisez comme nom de classe, alors "String" (majuscule "S") est préférable. Cette convention ne semble plus valable: si vous utilisez Visual Studio 2015 et essayez de l'écrire String, vous suggérer de "simplifier votre code", en le transportant vers string...
Massimiliano Kraus

166

Les minuscules stringsont un alias pour System.String. Ils sont les mêmes en C#.

Il y a un débat quant à savoir si vous devez utiliser les types de systèmes ( System.Int32, System.String, etc.) types ou C# aliases( int, string, etc.). Je crois personnellement que vous devriez utiliser le C# aliases, mais c'est juste ma préférence personnelle.


4
Voilà le problème, ce ne sont pas des alias 'C #', ce sont des alias 'C'. Il n'y a pas de «chaîne» ou «int» natif dans le langage C #, juste du sucre syntaxique.
Quarkly

16
Je ne sais pas d'où vient "C", car la spécification du langage C # 5 indique "La chaîne de mots clés est simplement un alias pour la classe System.String prédéfinie." Page 85, paragraphe 4.2.4. Tous les langages de haut niveau sont du sucre syntaxique sur les jeux d'instructions CPU et le bytecode.
aiodintsov

157

stringest juste un alias pour System.String. Le compilateur les traitera de manière identique.

La seule différence pratique est la mise en évidence de la syntaxe comme vous le mentionnez, et que vous devez écrire using Systemsi vous utilisez String.


Vous n'avez pas besoin de préfixer System pour utiliser String.
Joe Ratzer

18
Vous devez inclure un using Systemlors de l'utilisation String, sinon vous obtenez l'erreur suivante:The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
Ronald

144

Les deux sont les même. Mais du point de vue des directives de codage, il est préférable d'utiliser à la stringplace de String. C'est ce que les développeurs utilisent généralement. par exemple, au lieu d'utiliser, Int32nous utilisons inttel intquel alias pourInt32

FYI "La chaîne de mots clés est simplement un alias pour la classe prédéfinie System.String." - Spécification du langage C # 4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx


121

Comme le disent les autres, ce sont les mêmes. Règles StyleCop, par défaut, vous appliquer à utiliser stringcomme une meilleure pratique de style de code C #, sauf en cas de référencement des System.Stringfonctions statiques, tels que String.Format, String.Join, String.Concat, etc ...


4
Je ne savais pas que StyleCop marquerait l'utilisation de String - à l'exception des méthodes statiques. Je pense que c'est génial car c'est comme ça que je l'utilise toujours: chaîne pour les déclarations de type et chaîne lorsque j'accède aux membres statiques.
Goyuix

102

Nouvelle réponse après 6 ans et 5 mois (procrastination).

Tandis que stringest un mot-clé C # réservé qui a toujours une signification fixe, Stringest juste un identifiant ordinaire qui pourrait faire référence à n'importe quoi. Selon les membres du type actuel, l'espace de noms actuel et les usingdirectives appliquées et leur placement Stringpeuvent être une valeur ou un type distinct de global::System.String.

Je fournirai deux exemples où les usingdirectives ne serviront à rien .


Tout d'abord, quand Stringest une valeur du type actuel (ou une variable locale):

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

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

Ce qui précède ne sera pas compilé car IEnumerable<> aucun membre non statique Formatn'est appelé et aucune méthode d'extension ne s'applique. Dans le cas ci-dessus, il peut toujours être possible d'utiliser Stringdans d'autres contextes où un type est la seule possibilité syntaxiquement. Par exemple, String local = "Hi mum!";pourrait être OK (en fonction de l'espace de noms et des usingdirectives).

Pire: dire String.Concat(someSequence) ira probablement (selon les usings) à la méthode d'extension Linq Enumerable.Concat. Il n'ira pas à la méthode statique string.Concat.


Deuxièmement, lorsque String est un autre type , imbriqué dans le type actuel:

class MyPiano
{
  protected class String
  {
  }

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

Aucune instruction de la Exampleméthode ne se compile. Voici Stringtoujours un piano chaîne , MyPiano.String. Aucun membre ( staticou non) Formatn'existe dessus (ou n'est hérité de sa classe de base). Et la valeur"Goodbye" ne peut pas y être convertie.


4
Je suppose que pour être diabolique, on pourrait: using String = System.Int32; using Int32 = System.String; et puis compter les bugs.
Steve

7
c'est la bonne réponse. stringest System.String. Stringpourrait être n'importe quoi.
Dave Cousineau

Convenu @DaveCousineau - c'est le point de l'alias. Vous pouvez créer un autre Stringtype qui ne serait pas défini sur l'objet System.String. Départ: blog.paranoidcoding.com/2019/04/08/…
Kristopher

"Le mot clé stringa une signification concrète en C #. C'est le type System.Stringqui existe dans l'assembly d'exécution principal. Le runtime comprend intrinsèquement ce type et fournit les capacités attendues par les développeurs stringsdans .NET. Sa présence est si critique pour C # que si ce type ne fonctionne pas n'existe pas, le compilateur se fermera avant d'essayer d'analyser une ligne de code. Il stringa donc une signification précise et sans ambiguïté dans le code C #. L'identifiant Stringn'a cependant aucune signification concrète en C #. C'est un identifiant qui passe par toutes les règles de recherche de nom. comme Widget, Student, etc ... »
Kristopher



88

Contre ce qui semble être une pratique courante parmi d'autres programmeurs, je préfère Stringplus string, juste pour souligner le fait qu'il Strings'agit d'un type de référence, comme l'a mentionné Jon Skeet.



78

Je voudrais juste ajouter ceci à la réponse lfousts, du livre Ritchers:

La spécification du langage C # stipule: "Pour une question de style, l'utilisation du mot-clé est préférée à l'utilisation du nom complet du type de système." Je suis en désaccord avec la spécification de la langue; Je préfère utiliser les noms de type FCL et éviter complètement les noms de type primitifs. En fait, je souhaite que les compilateurs n'offrent même pas les noms de type primitifs et obligent les développeurs à utiliser à la place les noms de type FCL. Voici mes raisons:

  • J'ai vu un certain nombre de développeurs confus, ne sachant pas s'il fallait utiliser une chaîne ou une chaîne dans leur code. Parce que dans la chaîne C # (un mot-clé) correspond exactement à System.String (un type FCL), il n'y a aucune différence et l'un ou l'autre peut être utilisé. De même, j'ai entendu certains développeurs dire que int représente un entier 32 bits lorsque l'application s'exécute sur un système d'exploitation 32 bits et qu'il représente un entier 64 bits lorsque l'application s'exécute sur un système d'exploitation 64 bits. Cette affirmation est absolument fausse: en C #, un int correspond toujours à System.Int32 et représente donc un entier 32 bits quel que soit le système d'exploitation sur lequel le code s'exécute. Si les programmeurs utilisaientInt32 dans leur code, cette confusion potentielle est également éliminée.

  • En C #, les mappages longs vers System.Int64 , mais dans un langage de programmation différent, long peuvent mapper vers un Int16 ou Int32 . En fait, C ++ / CLI traite longtemps comme un Int32 . Quelqu'un qui lit le code source dans une langue pourrait facilement mal interpréter l'intention du code s'il était habitué à programmer dans un autre langage de programmation. En fait, la plupart des langues ne traiteront même pas longtemps comme un mot-clé et ne compileront pas le code qui l'utilise.

  • Le FCL possède de nombreuses méthodes dont les noms de type font partie de leurs noms de méthode. Par exemple, le type BinaryReader propose des méthodes telles que ReadBoolean , ReadInt32 , ReadSingle , etc. Le type System.Convert propose des méthodes telles que ToBoolean , ToInt32 , ToSingle , etc. Bien qu'il soit légal d'écrire le code suivant, la ligne avec float me semble très peu naturelle, et il n'est pas évident que la ligne soit correcte:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • De nombreux programmeurs qui utilisent exclusivement C # ont tendance à oublier que d'autres langages de programmation peuvent être utilisés contre le CLR, et à cause de cela, les mécanismes C # se glissent dans le code de bibliothèque de classes. Par exemple, le FCL de Microsoft est presque exclusivement écrit en C # et les développeurs de l'équipe FCL ont maintenant introduit des méthodes dans la bibliothèque telles que Array « de GetLongLength , qui renvoie une Int64 valeur qui est une longue en C # , mais pas dans d' autres langues (comme C ++ / CLI). Un autre exemple est System.Linq.Enumerable de LongCount méthode.

Je n'ai pas eu son opinion avant de lire le paragraphe complet.


72

Chaîne (System.String ) est une classe de la bibliothèque de classes de base. string (minuscule) est un travail réservé en C # qui est un alias pour System.String. Int32 vs int est une situation similaire Boolean vs. bool. Ces mots clés spécifiques au langage C # vous permettent de déclarer des primitives dans un style similaire à C.


67

Stringn'est pas un mot-clé et il peut être utilisé comme identifiant alors qu'il stringest un mot-clé et ne peut pas être utilisé comme identifiant. Et du point de vue fonctionnel, les deux sont identiques.


67

C'est une question de convention, vraiment. stringressemble plus au style C / C ++. La convention générale consiste à utiliser les raccourcis fournis par votre langue choisie (int / Int pour Int32). Cela vaut pour "objet" etdecimal aussi.

Théoriquement, cela pourrait aider à porter du code dans une future norme 64 bits dans laquelle "int" pourrait signifier Int64, mais ce n'est pas le point, et je m'attendrais à ce que tout assistant de mise à niveau modifie toutes les intréférences de Int32toute façon juste pour être sûr.


66

Venir en retard à la fête: j'utilise les types CLR 100% du temps (enfin, sauf si forcé d'utiliser le type C #, mais je ne me souviens pas quand c'était la dernière fois).

J'ai commencé à le faire il y a des années, selon les livres CLR de Ritchie. Il était logique pour moi que tous les langages CLR doivent finalement être en mesure de prendre en charge l'ensemble des types CLR, donc l'utilisation des types CLR vous-même a fourni un code plus clair et peut-être plus "réutilisable".

Maintenant que je le fais depuis des années, c'est une habitude et j'aime la coloration que VS montre pour les types CLR.

Le seul véritable inconvénient est que la saisie semi-automatique utilise le type C #, donc je finis par retaper les types générés automatiquement pour spécifier le type CLR à la place.

De plus, maintenant, quand je vois "int" ou "string", cela me semble vraiment mal, comme si je regardais le code C des années 70.


49

Il n'y a pas de différence.

Le mot clé C # stringcorrespond au type .NET System.String- c'est un alias qui respecte les conventions de dénomination du langage.

De même, les intcartesSystem.Int32 .


Dans une version 64 bits, int correspond à System.Int64 (8 octets), dans une version 32 bits, il correspond à System.Int32 (4 octets)
Alex

1
IntPtr et UIntPtr sont les seuls types qui changent de taille en fonction de la plateforme (sans tenir compte des types de pointeurs réels comme int*et des types composés de [U] IntPtrs ou de pointeurs réels).
P Daddy

45

Il y a une citation sur cette question de le livre Daniel Solis .

Tous les types prédéfinis sont mappés directement aux types .NET sous-jacents. Les noms de type C # (chaîne) sont simplement des alias pour les types .NET (String ou System.String), donc l'utilisation des noms .NET fonctionne bien syntaxiquement, bien que cela soit déconseillé. Dans un programme C #, vous devez utiliser les noms C # plutôt que les noms .NET.


41

chaîne est un mot clé et vous ne pouvez pas utiliser de chaîne comme identifiant.

La chaîne n'est pas un mot clé et vous pouvez l'utiliser comme identifiant:

Exemple

string String = "I am a string";

Le mot string - clé est un alias car en System.Stringdehors du problème de mot-clé, les deux sont exactement équivalents.

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

2
La seule petite différence est que si vous utilisez la classe String, vous devez importer l'espace de noms System au-dessus de votre fichier, alors que vous n'avez pas à le faire lorsque vous utilisez le mot clé string.
Uttam

Il existe des cas d'utilisation simples où la déclaration d'égalité échouerait ... Tels que la définition d'un type d'appel String dans l'espace de noms blah et l'importation de cet espace de noms dans le fichier dans lequel la déclaration d'égalité est exécutée.
rick

40

Oui, ce n'est pas une différence entre eux, tout comme les boolet Boolean.


40

@JaredPar (développeur du compilateur C # et utilisateur prolifique de SO!) A écrit un excellent article de blog sur ce problème. Je pense que cela vaut la peine d'être partagé ici. C'est une belle perspective sur notre sujet.

stringvs Stringn'est pas un débat de style

[...]

Le mot-clé stringa une signification concrète en C #. Il s'agit du type System.Stringqui existe dans l'assembly d'exécution principal. Le runtime comprend intrinsèquement ce type et fournit les capacités que les développeurs attendent pour les chaînes dans .NET. Sa présence est si critique pour C # que si ce type n'existe pas, le compilateur se fermera avant d'essayer même d'analyser une ligne de code. A donc stringune signification précise et non ambiguë dans le code C #.

L'identifiant Stringn'a cependant aucune signification concrète en C #. Il est un identifiant qui passe par toutes les règles recherche le nom comme Widget, Student, etc ... Il peut se lier à la chaîne ou il pourrait se lier à un type dans une autre assemblée entièrement dont les buts peuvent être tout à fait différent de celui string. Pire, il pourrait être défini d'une manière telle qu'un code comme String s = "hello"; a continué de compiler.

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

La signification réelle de Stringdépendra toujours de la résolution du nom. Cela signifie que cela dépend de tous les fichiers source du projet et de tous les types définis dans tous les assemblys référencés. Bref il faut pas mal de contexte pour savoir ce que cela signifie.

Il est vrai que dans la grande majorité des cas Stringet stringse liera au même type. Mais l'utilisation Stringsignifie toujours que les développeurs laissent leur programme à l'interprétation dans des endroits où il n'y a qu'une seule bonne réponse. Quand Stringse lie au mauvais type, cela peut laisser les développeurs déboguer pendant des heures, déposer des bogues sur l'équipe du compilateur et perdre généralement du temps qui aurait pu être économisé en utilisant string.

Une autre façon de visualiser la différence est avec cet exemple:

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

Beaucoup diront que même si ces informations sont techniquement exactes, leur utilisation Stringest toujours très bien car il est extrêmement rare qu'une base de code définisse un type de ce nom. Ou que lorsqu'il Stringest défini, c'est le signe d'une mauvaise base de code.

[...]

Vous verrez que cela Stringest défini pour un certain nombre d'objectifs tout à fait valides: assistants de réflexion, bibliothèques de sérialisation, lexers, protocoles, etc. Pour n'importe laquelle de ces bibliothèques Stringvsstring a des conséquences réelles selon l'endroit où le code est utilisé.

Alors souvenez-vous que lorsque vous voyez le débat Stringcontre string, il s'agit de sémantique, pas de style. Le choix de la chaîne donne une signification claire à votre base de code. Choisir Stringn'est pas mal, mais cela laisse la porte ouverte à des surprises à l'avenir.

Remarque: J'ai copié / collé la plupart des articles de blog pour des raisons d'archivage. J'ignore certaines parties, je vous recommande donc de sauter et de lire le blog si vous le pouvez.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.