Question

Dans .NET, quelle est la différence entre String.Empty et "" , et sont-ils interchangeables ou existe-t-il des problèmes de référence ou de localisation sous-jacents autour L’égalité que String.Empty garantira ne pose pas de problème?

Était-ce utile?

La solution

Dans .NET avant la version 2.0, "" crée un objet tandis que string.Empty ne crée aucun objet ref , ce qui rend string.Empty plus efficace.

Dans les versions 2.0 et ultérieures de .NET, toutes les occurrences de "" " font référence au même littéral de chaîne, ce qui signifie que "/ <; code> est équivalent à < code> .Vide , mais pas aussi rapide que .Length == 0 .

.Length == 0 est l'option la plus rapide, mais .Empty permet d'obtenir un code légèrement plus propre.

Consultez la spécification .NET pour plus d'informations .

Autres conseils

Les réponses précédentes étaient correctes pour .NET 1.1 (regardez la date du message auquel elles ont été associées: 2003). À partir de .NET 2.0 et ultérieur, il n'y a pratiquement pas de 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/ bibliothèque / aa691090 (VS.71) .aspx

  

Chaque littéral de chaîne n'aboutit 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 message de Brad Abram

En résumé, le résultat pratique de """ String.Empty est nul. L’Equipe commune d’évaluation le saura à la fin.

J’ai personnellement constaté que JIT est bien plus intelligent que moi et j’essaie donc de ne pas être trop malin avec des optimisations de micro-compilateurs comme celle-là. L'ECE se déroulera pendant () boucles, supprimera le code redondant, les méthodes en ligne, etc. mieux et à des moments plus appropriés que ce que I ou le compilateur C # aurait jamais pu anticiper. 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 utiliser String.Empty dans une instruction switch car ce n'est pas une constante.

Une autre différence est que String.Empty génère un code CIL plus volumineux. Bien que le code de référencement "&"; et String.Empty a la même longueur, le compilateur n'optimise pas la concaténation de chaînes (voir la section article de blog ) 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 
}

Les réponses ci-dessus sont techniquement correctes, mais vous voudrez peut-être vraiment utiliser pour une meilleure lisibilité du code et une chance moindre qu'une exception soit String.IsNullOrEmpty (s)

J'ai tendance à utiliser String.Empty plutôt que "" " pour une raison simple mais pas évidente: & & 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & & 6593; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; / code> ne sont PAS identiques, le premier contient en réalité 16 caractères de largeur zéro. De toute évidence, aucun développeur compétent ne mettra de code zéro largeur dans son code, mais s’ils y parviennent, cela peut être un cauchemar de maintenance.

Notes:

  • J'ai utilisé U + FEFF dans cette section. exemple.

  • Vous ne savez pas si SO va manger ces caractères, mais essayez vous-même avec l'un des nombreux caractères de largeur zéro

  • Je ne l'ai compris 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, il agira donc littéralement: lors de la première utilisation, il sera   créé et pour les utilisations suivantes, sa référence est renvoyée. Seulement un   L’instance de " sera stockée en mémoire quel que soit le nombre de fois   utilise le! Je ne vois pas de pénalités 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 VB.NET et C #   applications. Alors, pourquoi rechercher une référence chaque fois que vous avez besoin de " "   lorsque vous avez cette référence dans String.Empty ?

Référence: String.Empty vs " "

String.Empty ne crée pas d'objet alors que " " Est-ce que. Comme ici , la différence est triviale, cependant.

Toutes les instances de " " sont les mêmes, littéral de chaîne interné (ou ils devraient l'être). Ainsi, vous ne lancerez vraiment pas un nouvel objet sur le tas chaque fois que vous utiliserez " " mais juste en créant une référence au même objet, interné. Cela dit, je préfère string.Empty. Je pense que cela rend le code plus lisible.

string mystring = "";
ldstr ""

ldstr insère une nouvelle référence d'objet dans un littéral de chaîne stocké dans les métadonnées.

string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty

ldsfld place la valeur d'un champ statique dans la pile d'évaluation

J'ai tendance à utiliser String.Empty au lieu de "" " car IMHO, c'est plus clair et moins VB-ish.

Pour ce faire, du point de vue de Entity Framework: les versions 6.1.3 d’EF semblent traiter String.Empty et """ différemment lors de la validation.

string.Empty est traité comme une valeur null à des fins de validation et génère une erreur de validation s'il est utilisé dans un champ Required (attribué). où en tant que " " passera la validation et ne jettera 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 en 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 la fonction.

public void test(int i=0,string s="")
    {
      // Function Body
    }
  

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 y arrivera! "

Voici quelques résultats Roslyn x64 en janvier 2019. Malgré les remarques de consensus exprimées dans les autres réponses figurant sur cette page, il ne me semble pas que l'actuelle ECE x64 traite tous ces cas. à l'identique, en fin de compte.

Notez cependant que seul l'un de ces exemples appelle String.Concat , et j'imagine que c'est pour des raisons obscures de correction (par opposition à un oubli d'optimisation). Les autres différences semblent plus difficiles à expliquer.

par défaut (String) & nbsp; + & nbsp; {default (String), & nbsp; " ;, & nbsp; 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

""" & nbsp; + & nbsp; {default (String), & nbsp; " ;, & nbsp; 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 & nbsp; + & nbsp; {default (String), & nbsp; " ;, & nbsp; 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


Détails du test

Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false

Lorsque vous parcourez visuellement le code, " " apparaît colorisé de la même manière que les chaînes. 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 intuitez le sens.

Repérez les chaînes (la colorisation du débordement de la pile n’aide pas vraiment, mais en VS cela 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;

Tout le monde ici a donné une bonne clarification théorique. J'ai eu 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

Donc, il semble que " Null " signifie absolument nul & amp; "String.Empty" signifie qu'il contient une sorte de valeur, mais qu'il est vide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top