Domanda

In .NET, qual è la differenza tra String.Empty e " " , e sono intercambiabili, o c'è qualche riferimento sottostante o problemi di localizzazione in giro uguaglianza che String.Empty garantirà non essere un problema?

È stato utile?

Soluzione

In .NET prima della versione 2.0, " " crea un oggetto mentre string.Empty non crea alcun oggetto ref , che rende string.Empty altro efficiente.

Nella versione 2.0 e successive di .NET, tutte le occorrenze di " " si riferiscono alla stessa stringa letterale, il che significa che " " è equivalente a < code> .Empty , ma non ancora veloce come .Length == 0 .

.Length == 0 è l'opzione più veloce, ma .Empty rende il codice leggermente più pulito.

Vedi le le specifiche .NET per ulteriori informazioni .

Altri suggerimenti

  

qual è la differenza tra String.Empty e " " ;, e loro sono   interchangable

string.Empty è un campo di sola lettura mentre " " è una costante di tempo di compilazione. I luoghi in cui si comportano diversamente sono:

Valore del parametro predefinito in C # 4.0 o versione successiva

void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
    //... implementation
}

Espressione maiuscola nell'istruzione switch

string str = "";
switch(str)
{
    case string.Empty: // Error: A constant value is expected. 
        break;

    case "":
        break;

}

Argomenti degli attributi

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
//        or array creation expression of an attribute parameter type

Le risposte precedenti erano corrette per .NET 1.1 (guarda la data del post che hanno collegato: 2003). A partire da .NET 2.0 e versioni successive, non vi è sostanzialmente alcuna differenza. La JIT finirà comunque per fare riferimento allo stesso oggetto sull'heap.

Secondo la specifica C #, sezione 2.4.4.5: http://msdn.microsoft.com/en-us/ biblioteca / aa691090 (VS.71) aspx

  

Ogni stringa letterale non comporta necessariamente una nuova istanza di stringa. Quando due o più valori letterali di stringa equivalenti secondo l'operatore di uguaglianza di stringa (Sezione 7.9.7) compaiono nello stesso assieme, questi valori letterali di stringa fanno riferimento alla stessa istanza di stringa.

Qualcuno lo menziona persino nei commenti del post di Brad Abram

In breve, il risultato pratico di " " vs. String.Empty è zero. Il JIT lo capirà alla fine.

Ho scoperto, personalmente, che JIT è molto più intelligente di me e quindi cerco di non essere troppo intelligente con ottimizzazioni del micro-compilatore del genere. Il JIT si aprirà per () loop, rimuoverà il codice ridondante, i metodi inline, ecc. Meglio e in momenti più appropriati di quanto io o il compilatore C # potremmo mai anticipare prima. Lascia che JIT faccia il suo lavoro :)

String.Empty è un campo di sola lettura mentre " " è una const . Ciò significa che non è possibile utilizzare String.Empty in un'istruzione switch perché non è una costante.

Un'altra differenza è che String.Empty genera un codice CIL più grande. Mentre il codice per fare riferimento a " " e String.Empty ha la stessa lunghezza, il compilatore non ottimizza la concatenazione di stringhe (vedi post di blog ) per argomenti String.Empty. Le seguenti funzioni equivalenti

string foo()
{
    return "foo" + "";
}
string bar()
{
    return "bar" + string.Empty;
}

genera questo 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 
}

Le risposte di cui sopra sono tecnicamente corrette, ma ciò che potresti davvero voler usare, per la migliore leggibilità del codice e la minima possibilità di un'eccezione è String.IsNullOrEmpty (s)

Tendo a usare String.Empty anziché " " per un motivo semplice, ma non ovvio: " & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; & # 65279; " e " " NON sono gli stessi, il primo contiene effettivamente 16 caratteri di larghezza zero. Ovviamente nessuno sviluppatore competente inserirà caratteri e larghezza zero nel loro codice, ma se entrano lì, può essere un incubo per la manutenzione.

Note:

Usa String.Empty anziché "".

  

Questo è più per la velocità rispetto all'utilizzo della memoria ma è un suggerimento utile. Il    " " è un valore letterale, quindi agirà come un valore letterale: al primo utilizzo è   creato e per i seguenti usi viene restituito il riferimento. Solo uno   l'istanza di " " verrà archiviata in memoria indipendentemente da quante volte   usalo! Non vedo alcuna penalità di memoria qui. Il problema è quello   ogni volta che si utilizza " " , viene eseguito un ciclo di confronto per verificare se    " " è già nel pool interno. Dall'altro lato, String.Empty   è un riferimento a un " " archiviato nella area di memoria di .NET Framework .    String.Empty punta allo stesso indirizzo di memoria per VB.NET e C #   applicazioni. Quindi perché cercare un riferimento ogni volta che hai bisogno di " "   quando hai quel riferimento in String.Empty ?

Riferimento: String.Empty vs " "

String.Empty non crea un oggetto mentre " " lo fa. La differenza, come sottolineato qui , è banale, tuttavia.

Tutte le istanze di " " sono le stesse stringhe letterali internate (o dovrebbero essere). Quindi non lancerai un nuovo oggetto sull'heap ogni volta che usi " " ma semplicemente creando un riferimento allo stesso oggetto internato. Detto questo, preferisco string.Empty. Penso che renda il codice più leggibile.

string mystring = "";
ldstr ""

ldstr invia un nuovo riferimento all'oggetto a una stringa letterale memorizzata nei metadati.

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

ldsfld inserisce il valore di un campo statico nello stack di valutazione

Tendo a usare String.Empty invece di " " perché IMHO è più chiaro e meno VB-ish.

Da questo punto di vista dal punto di vista di Entity Framework: le versioni EF 6.1.3 sembrano trattare String.Empty e " " diversamente durante la convalida.

string.Empty viene trattato come un valore null ai fini della validazione e genererà un errore di validazione se viene utilizzato su un campo obbligatorio (attribuito); dove come " " passerà la convalida e non genererà l'errore.

Questo problema può essere risolto in EF 7+. Riferimento: - https://github.com/aspnet/EntityFramework/issues/2610 ).

Modifica: [Obbligatorio (AllowEmptyStrings = true)] risolverà questo problema, consentendo la validazione di string.Empty.

Poiché String.Empty non è una costante di compilazione non è possibile utilizzarlo come valore predefinito nella definizione della funzione.

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

Eric Lippert ha scritto (17 giugno 2013):
" Il primo algoritmo su cui abbia mai lavorato nel compilatore C # è stato l'ottimizzatore che gestisce le concatenazioni di stringhe. Sfortunatamente non sono riuscito a portare queste ottimizzazioni sulla base di codice di Roslyn prima di partire; speriamo che qualcuno ci arrivi! "

Ecco alcuni risultati Roslyn x64 a gennaio 2019. Nonostante le osservazioni di consenso delle altre risposte in questa pagina, non mi sembra che l'attuale JIT x64 stia trattando tutti questi casi allo stesso modo, quando tutto è detto e fatto.

Nota in particolare, tuttavia, che solo uno di questi esempi finisce per chiamare String.Concat , e suppongo che ciò sia per oscure ragioni di correttezza (al contrario di una svista di ottimizzazione). Le altre differenze sembrano più difficili da spiegare.


predefinito (stringa) & 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


Dettagli del test

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

Quando esegui la scansione visiva del codice, " " appare colorato come sono colorate le stringhe. string.Empty sembra un normale accesso ai membri della classe. Durante una rapida occhiata, è più facile individuare " " o intuire il significato.

Trova le stringhe (la colorazione di overflow dello stack non aiuta esattamente, ma in VS questo è più ovvio):

var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;

Tutti qui hanno fornito alcuni buoni chiarimenti teorici. Avevo un dubbio simile. Quindi ho provato un codice di base su di esso. E ho trovato la differenza. Ecco la differenza.

string str=null;
Console.WriteLine(str.Length);  // Exception(NullRefernceException) for pointing to null reference. 


string str = string.Empty;
Console.WriteLine(str.Length);  // 0

Quindi sembra " Null " significa assolutamente nullo & amp; & Quot; String.Empty " significa che contiene un qualche tipo di valore, ma è vuoto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top