Réponses:
Dans .NET avant la version 2.0, ""
crée un objet tout en string.Empty
ne créant aucune référence d' objet , ce qui rend string.Empty
plus efficace.
Dans la version 2.0 et les versions ultérieures de .NET, toutes les occurrences de ""
font référence au même littéral de chaîne, ce qui signifie qu'il ""
est équivalent à .Empty
, mais pas aussi rapide que .Length == 0
.
.Length == 0
est l'option la plus rapide, mais .Empty
permet un code légèrement plus propre.
string.IsNullOrEmpty( stringVar )
.
quelle est la différence entre String.Empty et "", et sont-ils interchangeables
string.Empty
est un champ en lecture seule alors qu'il ""
s'agit d'une constante de temps de compilation. Les endroits où ils se comportent différemment sont:
Valeur de paramètre par défaut en C # 4.0 ou supérieur
void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
//... implementation
}
Expression de casse dans l'instruction switch
string str = "";
switch(str)
{
case string.Empty: // Error: A constant value is expected.
break;
case "":
break;
}
Arguments d'attribut
[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type
String.Empty
argument comme argument dans la plupart des cas. Vous avez raison que tous les exemples le montrent you simply can't put a (run-time) "value" into (compile-time) metadata
et c'est ce que les exemples visent à montrer.
Les réponses précédentes étaient correctes pour .NET 1.1 (regardez la date du message qu'ils ont lié: 2003). À partir de .NET 2.0 et versions ultérieures, il n'y a essentiellement aucune différence. Le JIT finira par référencer le même objet sur le tas de toute façon.
Selon la spécification C #, section 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx
Chaque littéral de chaîne n'entraîne pas nécessairement une nouvelle instance de chaîne. Lorsque deux ou plusieurs littéraux de chaîne équivalents selon l'opérateur d'égalité de chaîne (Section 7.9.7) apparaissent dans le même assemblage, ces littéraux de chaîne font référence à la même instance de chaîne.
Quelqu'un le mentionne même dans les commentaires du post de Brad Abram
En résumé, le résultat pratique de "" par rapport à String.Empty est nul. Le JIT le découvrira à la fin.
J'ai trouvé, personnellement, que le JIT est bien plus intelligent que moi et j'essaie donc de ne pas devenir trop intelligent avec des optimisations de micro-compilateurs comme ça. Le JIT se déroulera pour les boucles (), supprimera le code redondant, les méthodes en ligne, etc. mieux et à des moments plus appropriés que moi ou le compilateur C # n'aurais jamais pu prévoir auparavant. Laissez le JIT faire son travail :)
String.Empty
est un champ en lecture seule tandis que ""
est un const . Cela signifie que vous ne pouvez pas l'utiliser String.Empty
dans une instruction switch car ce n'est pas une constante.
default
mot - clé, nous pouvons promouvoir la lisibilité sans, empêcher les modifications accidentelles et avoir une constante de compilation, mais pour être honnête, je pense toujours que String.Empty est plus lisible que par défaut, mais plus lent à taper
Une autre différence est que String.Empty génère un code CIL plus volumineux. Alors que le code pour référencer "" et String.Empty est de la même longueur, le compilateur n'optimise pas la concaténation de chaînes (voir le blog d' Eric Lippert ) pour les arguments String.Empty. Les fonctions équivalentes suivantes
string foo()
{
return "foo" + "";
}
string bar()
{
return "bar" + string.Empty;
}
générer cet IL
.method private hidebysig instance string foo() cil managed
{
.maxstack 8
L_0000: ldstr "foo"
L_0005: ret
}
.method private hidebysig instance string bar() cil managed
{
.maxstack 8
L_0000: ldstr "bar"
L_0005: ldsfld string [mscorlib]System.String::Empty
L_000a: call string [mscorlib]System.String::Concat(string, string)
L_000f: ret
}
"bar " + (ok ? "" : "error")
Les réponses ci-dessus sont techniquement correctes, mais ce que vous voudrez peut-être vraiment utiliser, pour une meilleure lisibilité du code et moins de risques d'exception, c'est String.IsNullOrEmpty (s)
--foo=$BAR
vous souhaiterez probablement faire la différence entre le fait d'oublier de définir une variable env et celui de ne pas passer le drapeau du tout. string.IsNullOrEmpty
est souvent une odeur de code que vous n'avez pas validé correctement vos entrées ou que vous faites des choses étranges. Vous ne devriez généralement pas accepter de chaînes vides lorsque vous comptez vraiment les utiliser null
, ou quelque chose comme un type Maybe / Option.
J'ai tendance à utiliser String.Empty
plutôt que ""
pour une raison simple, mais pas évidente:
""
et ne ""
sont pas les mêmes, le premier a en fait 16 caractères de largeur nulle. Évidemment, aucun développeur compétent ne mettra de caractères de largeur nulle dans leur code, mais s'ils y parviennent, cela peut être un cauchemar de maintenance.
Remarques:
J'ai utilisé U + FEFF dans cet exemple.
Je ne sais pas si SO va manger ces caractères, mais essayez-le vous-même avec l'un des nombreux caractères de largeur nulle
Je ne l'ai découvert que grâce à https://codegolf.stackexchange.com/
Utilisez String.Empty
plutôt que ""
.
C'est plus pour la vitesse que pour l'utilisation de la mémoire, mais c'est un conseil utile. Le
""
est un littéral et agira donc comme un littéral: lors de la première utilisation, il est créé et pour les utilisations suivantes, sa référence est renvoyée. Une seule instance de""
sera stockée en mémoire, peu importe combien de fois nous l'utilisons! Je ne vois aucune pénalité de mémoire ici. Le problème est que chaque fois que le""
est utilisé, une boucle de comparaison est exécutée pour vérifier si le""
est déjà dans le pool interne. De l'autre côté,String.Empty
est une référence à un""
stocké dans la zone de mémoire .NET Framework .String.Empty
pointe vers la même adresse mémoire pour les applications VB.NET et C #. Alors pourquoi chercher une référence à chaque fois que vous en avez besoin ?""
lorsque vous avez cette référence dansString.Empty
Référence: String.Empty
vs""
String.Empty ne crée pas d'objet contrairement à "". La différence, comme indiqué ici , est cependant insignifiante.
Toutes les instances de "" sont les mêmes, littérales de chaînes internes (ou elles devraient l'être). Donc, vous ne lancerez vraiment pas un nouvel objet sur le tas chaque fois que vous utilisez "", mais vous créerez simplement une référence au même objet interné. Cela dit, je préfère la chaîne vide. Je pense que cela rend le code plus lisible.
Ça n'a pas d'importance!
Quelques discussions passées à ce sujet:
http://www.codinghorror.com/blog/archives/000185.html
string mystring = "";
ldstr ""
ldstr
envoie une nouvelle référence d'objet à un littéral de chaîne stocké dans les métadonnées.
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
pousse la valeur d'un champ statique sur la pile d'évaluation
J'ai tendance à utiliser à la String.Empty
place de ""
parce qu'à mon humble avis, c'est plus clair et moins VB-ish.
Eric Lippert a écrit (17 juin 2013):
"Le premier algorithme sur lequel j'ai travaillé dans le compilateur C # était l'optimiseur qui gère les concaténations de chaînes. Malheureusement, je n'ai pas réussi à porter ces optimisations sur la base de code de Roslyn avant de partir; j'espère que quelqu'un le fera allez-y! "
Voici quelques résultats de Roslyn x64 en janvier 2019. Malgré les remarques consensuelles des autres réponses sur cette page, il ne me semble pas que le JIT x64 actuel traite tous ces cas de manière identique, quand tout est dit et fait.
Notez en particulier, cependant, qu'un seul de ces exemples finit par appeler String.Concat
, et je suppose que c'est pour des raisons de correction obscures (par opposition à une surveillance d'optimisation). Les autres différences semblent plus difficiles à expliquer.
default (String) + {default (String), "", String.Empty}
static String s00() => default(String) + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s01() => default(String) + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s02() => default(String) + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
"" + {default (String), "", String.Empty}
static String s03() => "" + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s04() => "" + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s05() => "" + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
String.Empty + {default (String), "", String.Empty}
static String s06() => String.Empty + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s07() => String.Empty + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s08() => String.Empty + String.Empty;
mov rcx,[String::Empty]
mov rcx,qword ptr [rcx]
mov qword ptr [rsp+20h],rcx
mov rcx,qword ptr [rsp+20h]
mov rdx,qword ptr [rsp+20h]
call F330CF60 ; <-- String.Concat
nop
add rsp,28h
ret
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
En venant à cela d'un point de vue Entity Framework: EF versions 6.1.3 semble traiter String.Empty et "" différemment lors de la validation.
string.Empty est traité comme une valeur nulle à des fins de validation et générera une erreur de validation s'il est utilisé dans un champ Obligatoire (attribué); où "" passera la validation et ne générera pas l'erreur.
Ce problème peut être résolu dans EF 7+. Référence: - https://github.com/aspnet/EntityFramework/issues/2610 ).
Modifier: [Obligatoire (AllowEmptyStrings = true)] résoudra ce problème, permettant à string.Empty de valider.
Puisque String.Empty n'est pas une constante de compilation, vous ne pouvez pas l'utiliser comme valeur par défaut dans la définition de fonction.
public void test(int i=0,string s="")
{
// Function Body
}
public void test(int i=0, string s=string.Empty) {}
ne compilera pas et ne dira pas "La valeur par défaut du paramètre pour 's' doit être une constante de temps de compilation. La réponse d'OP fonctionne.
Lorsque vous scannez visuellement le code, "" apparaît colorisé comme les chaînes sont colorisées. string.Empty ressemble à un accès régulier aux membres de la classe. Lors d 'un rapide coup d' œil, il est plus facile de "" repérer ou de comprendre le sens.
Repérez les chaînes (la colorisation du débordement de la pile n'aide pas vraiment, mais en VS, c'est plus évident):
var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
\u00ad
.
Tout le monde ici a donné une bonne clarification théorique. J'avais un doute similaire. J'ai donc essayé un codage de base dessus. Et j'ai trouvé une différence. Voici la différence.
string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference.
string str = string.Empty;
Console.WriteLine(str.Length); // 0
Il semble donc que «Null» signifie absolument nul et «String.Empty» signifie qu'il contient une sorte de valeur, mais qu'il est vide.
""
versus string.Empty
. Ce n'est qu'en essayant de dire si la chaîne est vide que cela null
a été mentionné.
string.Empty
et quelle était la raison d'être de le déclarer aureadonly
lieu deconst
.