2009-11-10 11 views
63

Mi piacerebbe chiederti quale pensi sia il modo migliore (dura di meno/consuma meno risorse) per cancellare i contenuti al fine di riutilizzare un oggetto StringBuilder. Immaginate il seguente scenario:il modo migliore per cancellare i contenuti di .NET's StringBuilder

StringBuilder sb = new StringBuilder(); 
foreach(var whatever in whateverlist) 
{ 
    sb.Append("{0}", whatever); 
} 

//Perform some stuff with sb 

//Clear stringbuilder here 

//Populate stringbuilder again to perform more actions 
foreach(var whatever2 in whateverlist2) 
{ 
    sb.Append("{0}", whatever2); 
} 

E quando la compensazione StringBuilder Mi vengono in mente due possibilità:

sb = new StringBuilder(); 

o

sb.Length = 0; 

Qual è il modo migliore per cancellare e perché?

Grazie.

MODIFICA: accedo alla versione .NET 3.5 corrente.

+4

Non un risposta, ma interessante da leggere: http://bobondevelopment.com/2007/06/11/three-ways-to-clear-a-stringbuilder/ –

+1

Qual è il motivo per non includere il metodo StringBuilder.Clear() come alternativa ? –

+0

@Rune: C# 4.0 non è ancora uscito, è solo in 4.0. Su MSDN dice: Supportato in: 4. – jcollum

risposta

60

Se lo stai facendo in .NET 2.0 o 3.5, scrivere un metodo di estensione di farlo in questo modo:

/// <summary> 
///  Clears the contents of the string builder. 
/// </summary> 
/// <param name="value"> 
///  The <see cref="StringBuilder"/> to clear. 
/// </param> 
public static void Clear(this StringBuilder value) 
{ 
    value.Length = 0; 
    value.Capacity = 0; 
} 

Quindi, è possibile cancellare in questo modo:

someStringBuilder.Clear(); 

Poi, quando 4,0 esce, è possibile fosso il tuo metodo di estensione a favore della versione 4.0.

UPDATE: Probabilmente non è una buona idea impostare la Capacità su zero. Ciò garantirà le riallocazioni quando si aggiunge al builder, se si riutilizza la stessa istanza. Tuttavia, la memoria nell'istanza del builder non viene rilasciata finché non si imposta la Capacità su un valore molto piccolo (come 1). Il valore predefinito della proprietà Capacity è 16. Si potrebbe voler considerare l'utilizzo di 16, o (anche se è meno efficiente) impostando la capacità due volte:

  • impostarlo su 1 o pari a zero per cancellare la memoria
  • Set per il valore di capacità originale (che può differire da 16) per ripristinarlo.
+0

Metodo pulito. Proprio quello che stavo cercando. – abhi

+12

Si consiglia di non svuotare la capacità, tranne quando è noto che 'StringBuilder' abbia contenuto qualcosa * insolitamente * grande. Soprattutto nelle precedenti versioni di .net, se si costruiranno ripetutamente stringhe di oltre 42.500 caratteri, la cancellazione del buffer dopo ogni stringa causerà l'allocazione di oggetti aggiuntivi nell'Heap di oggetto di grandi dimensioni ogni volta che il buffer deve ricrescere. Questa è una brutta cosa. – supercat

+2

Impostare la capacità su 0 è un'idea interessante. Quando si usa Clear o si imposta semplicemente la lunghezza su 0, si può verificare una perdita di memoria quando Insert() viene usato ripetutamente, poiché la Capacità continua a crescere nonostante Clear. (vedi la mia domanda: http://stackoverflow.com/questions/29574469/memory-leak-in-stringbuilder-when-using-insert-and-clear –

15

Creare il nuovo StringBuilder. Il vecchio mantiene le risorse ad esso associate (buffer di lunghezza massima, ad esempio) che sono i migliori appena raccolti.

28

In .NET 4.0 è possibile chiamare sb.Clear() ma nelle versioni precedenti è necessario impostare sb.Length = 0.

Il metodo Clear() è stato aggiunto in .NET 4.0.

+1

Imposta anche la capacità di azzerare ... –

+12

Se stai riutilizzando, non vuoi riutilizzare il buffer? – GraemeF

+2

dipende dalla varianza di quanto è grande la stringa creata la prima volta rispetto alla stringa creata la seconda volta. O almeno lo direi così – Earlz

10

Penso che si stia facendo un'ottimizzazione prematura.

Scommetto che fare il sb.Length=0; sarebbe il modo più veloce per evitare di creare un altro oggetto e mettere da parte un altro oggetto affinché GC possa eventualmente raccogliere.

Penso che la creazione di un nuovo StringBuilder sarebbe la soluzione migliore per i problemi di memoria. e l'impostazione sb.Length sarebbe il colpo migliore per le preoccupazioni di velocità ..

10

da contenuti comunitaria in MSDN:

Per cancellare in modo efficace il vostro StringBuilder senza distruggerlo uso:

someStringBuilder.length = 0; 
someStringBuilder.capacity = 0; 

Questo distrugge entrambi i suoi contenuti e lo ridimensiona a zero. Come indicato sopra , la dimensione può influire sulle piccole applicazioni .

1

Direi che il modo migliore per eliminarlo è usare sb = new StringBuilder();. Detto questo, penso che sarebbe ancora meglio se creasse un nuovo oggetto generatore di stringhe del tutto.

EDIT

spero va da sé che questa è la soluzione migliore.

public StringBuilder MakeString(IEnumerable<CoolType> list) 
{ 
    StringBuilder sb = new StringBuilder(); 

    foreach(var whatever in list) 
    { 
     sb.Append("{0}", whatever); 
    } 
} 

var sb = MakeString(whateverList); 
// Do stuff 
// Clear stuff 
sb = MakeString(whateverList2); 
+5

sb = new StringBuilder() Sta facendo un nuovo oggetto generatore di stringhe. –

+0

Fare ciò rende completamente un nuovo oggetto generatore di stringhe. –

+0

Penso che Matt significhi dichiarare una nuova variabile per il nuovo 'StringBuilder'. –

2

Se si desidera ridurre l'utilizzo della memoria, utilizzare il CLR Profiler per verificare la quantità di memoria utilizzata dagli oggetti StringBuilder durante il loro ciclo di vita utilizzando i metodi descritti in precedenza. Quindi puoi accontentarti che l'opzione scelta è adatta alle tue esigenze e sta rilasciando le risorse di cui hai bisogno.

4

In .NET Framework 4 nuovi metodi sono stati introdotti nella classe StringBuilder. Il nome del metodo è "Cancella". Questo metodo consente di cancellare o rimuovere valori o dati dagli oggetti StringBuilder.

Ecco un esempio.

System.Text.StringBuilder objSB = new System.Text.StringBuilder(); 
    //Append values 
    objSB.Append("This is .Net Blog."); 
    objSB.Append("You can get latest C# Tips over here."); 

    //Display on screen 
    Response.Write(objSB.ToString()); 
    Response.Write("<br/><br/>"); 

    //Clear object using Clear method 
    objSB.Clear(); 

    //Append another values 
    objSB.Append("This blog is very useful for .Net Beginners"); 

    Response.Write("After Clear<br/><br/>"); 
    //Display on screen 
    Response.Write(objSB.ToString()); 
0

Basta chiamare Clear() il metodo è sufficiente impostare la lunghezza = 0, Possiamo impostare Capacità = 0 anche, se vogliamo salvare la memoria

public StringBuilder Clear() { 
     this.Length = 0; 
     return this; 
} 

Ref: In referencesource.microsoft.com

Problemi correlati