Classe System.Text.StringBuilder
Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.
La StringBuilder classe rappresenta un oggetto simile a una stringa il cui valore è una sequenza modificabile di caratteri.
StringBuilder e tipo String
Sebbene StringBuilder e String rappresentino entrambe le sequenze di caratteri, vengono implementate in modo diverso. String è un tipo non modificabile. Ovvero, ogni operazione che sembra modificare un String oggetto crea effettivamente una nuova stringa.
Ad esempio, la chiamata al String.Concat metodo nell'esempio C# seguente sembra modificare il valore di una variabile stringa denominata value
. Il metodo restituisce Concat infatti un value
oggetto con un valore e un indirizzo diversi dall'oggetto value
passato al metodo . Si noti che l'esempio deve essere compilato usando l'opzione del /unsafe
compilatore.
using System;
public class Example7
{
public unsafe static void Main()
{
string value = "This is the first sentence" + ".";
fixed (char* start = value)
{
value = String.Concat(value, "This is the second sentence. ");
fixed (char* current = value)
{
Console.WriteLine(start == current);
}
}
}
}
// The example displays the following output:
// False
let mutable value = "This is the first sentence" + "."
use start = fixed value
value <- System.String.Concat(value, "This is the second sentence. ")
use current = fixed value
printfn $"{start = current}"
// The example displays the following output:
// False
Per le routine che eseguono una manipolazione estesa delle stringhe (ad esempio le app che modificano una stringa più volte in un ciclo), la modifica di una stringa ripetutamente può comportare una riduzione significativa delle prestazioni. L'alternativa consiste nell'usare StringBuilder, ovvero una classe stringa modificabile. La mutabilità significa che una volta creata un'istanza della classe, può essere modificata aggiungendo, rimuovendo, sostituendo o inserendo caratteri.
Importante
Anche se la StringBuilder classe offre in genere prestazioni migliori rispetto alla String classe , non è consigliabile sostituire String automaticamente con StringBuilder ogni volta che si desidera modificare le stringhe. Le prestazioni dipendono dalle dimensioni della stringa, dalla quantità di memoria da allocare per la nuova stringa, dal sistema in cui viene eseguito il codice e dal tipo di operazione. È necessario essere pronti a testare il codice per determinare se StringBuilder effettivamente offre un miglioramento significativo delle prestazioni.
Prendere in considerazione l'uso della String classe in queste condizioni:
- Quando il numero di modifiche apportate dal codice a una stringa è ridotto. In questi casi, StringBuilder potrebbe offrire un miglioramento trascurabile o nessun miglioramento delle prestazioni rispetto Stringa .
- Quando si esegue un numero fisso di operazioni di concatenazione, in particolare con valori letterali stringa. In questo caso, il compilatore potrebbe combinare le operazioni di concatenazione in una singola operazione.
- Quando è necessario eseguire operazioni di ricerca estese durante la compilazione della stringa. La StringBuilder classe non dispone di metodi di ricerca come
IndexOf
oStartsWith
. Sarà necessario convertire l'oggetto StringBuilder in un oggetto String per queste operazioni e ciò può negare il vantaggio delle prestazioni dall'uso StringBuilderdi . Per altre informazioni, vedere la sezione Cercare il testo in un oggetto StringBuilder.
Prendere in considerazione l'uso della StringBuilder classe in queste condizioni:
- Quando si prevede che il codice esemplivi un numero sconosciuto di modifiche a una stringa in fase di progettazione, ad esempio quando si usa un ciclo per concatenare un numero casuale di stringhe che contengono l'input dell'utente.
- Quando si prevede che il codice apporta un numero significativo di modifiche a una stringa.
Funzionamento di StringBuilder
La StringBuilder.Length proprietà indica il numero di caratteri attualmente contenuti nell'oggetto StringBuilder . Se si aggiungono caratteri all'oggetto StringBuilder , la lunghezza aumenta fino a quando non è uguale alla dimensione della StringBuilder.Capacity proprietà, che definisce il numero di caratteri che l'oggetto può contenere. Se il numero di caratteri aggiunti determina il superamento della capacità corrente dell'oggetto StringBuilder , viene allocata una nuova memoria, il valore della Capacity proprietà viene raddoppiato, i nuovi caratteri vengono aggiunti all'oggetto StringBuilder e la relativa Length proprietà viene modificata. La memoria aggiuntiva per l'oggetto StringBuilder viene allocata dinamicamente fino a raggiungere il valore definito dalla StringBuilder.MaxCapacity proprietà . Quando viene raggiunta la capacità massima, non è possibile allocare ulteriore memoria per l'oggetto StringBuilder e tentare di aggiungere caratteri o espanderlo oltre la capacità massima genera un'eccezione OutOfMemoryException ArgumentOutOfRangeException o .
Nell'esempio seguente viene illustrato come un StringBuilder oggetto alloca nuova memoria e ne aumenta la capacità in modo dinamico man mano che la stringa assegnata all'oggetto si espande. Il codice crea un StringBuilder oggetto chiamando il costruttore predefinito (senza parametri). La capacità predefinita di questo oggetto è di 16 caratteri e la capacità massima è superiore a 2 miliardi di caratteri. L'aggiunta della stringa "Questa è una frase." comporta una nuova allocazione di memoria perché la lunghezza della stringa (19 caratteri) supera la capacità predefinita dell'oggetto StringBuilder . La capacità dell'oggetto raddoppia a 32 caratteri, viene aggiunta la nuova stringa e la lunghezza dell'oggetto è ora uguale a 19 caratteri. Il codice aggiunge quindi la stringa "Questa è una frase aggiuntiva". Al valore dell'oggetto StringBuilder 11 volte. Ogni volta che l'operazione di accodamento determina il superamento della capacità dell'oggetto StringBuilder , la capacità esistente viene raddoppiata e l'operazione Append ha esito positivo.
using System;
using System.Reflection;
using System.Text;
public class Example4
{
public static void Main()
{
StringBuilder sb = new StringBuilder();
ShowSBInfo(sb);
sb.Append("This is a sentence.");
ShowSBInfo(sb);
for (int ctr = 0; ctr <= 10; ctr++)
{
sb.Append("This is an additional sentence.");
ShowSBInfo(sb);
}
}
private static void ShowSBInfo(StringBuilder sb)
{
foreach (var prop in sb.GetType().GetProperties())
{
if (prop.GetIndexParameters().Length == 0)
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
}
Console.WriteLine();
}
}
// The example displays the following output:
// Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0
// Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19
// Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50
// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81
// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360
open System.Text
let showSBInfo (sb: StringBuilder) =
for prop in sb.GetType().GetProperties() do
if prop.GetIndexParameters().Length = 0 then
printf $"{prop.Name}: {prop.GetValue sb:N0} "
printfn ""
let sb = StringBuilder()
showSBInfo sb
sb.Append "This is a sentence." |> ignore
showSBInfo sb
for i = 0 to 10 do
sb.Append "This is an additional sentence." |> ignore
showSBInfo sb
// The example displays the following output:
// Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0
// Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19
// Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50
// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81
// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205
// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329
// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360
Imports System.Reflection
Imports System.Text
Module Example5
Public Sub Main()
Dim sb As New StringBuilder()
ShowSBInfo(sb)
sb.Append("This is a sentence.")
ShowSBInfo(sb)
For ctr As Integer = 0 To 10
sb.Append("This is an additional sentence.")
ShowSBInfo(sb)
Next
End Sub
Public Sub ShowSBInfo(sb As StringBuilder)
For Each prop In sb.GetType().GetProperties
If prop.GetIndexParameters().Length = 0 Then
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
End If
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0
' Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19
' Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50
' Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81
' Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112
' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143
' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174
' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205
' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236
' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267
' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298
' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329
' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360
Allocazione della memoria
La capacità predefinita di un StringBuilder oggetto è di 16 caratteri e la capacità massima predefinita è Int32.MaxValue. Questi valori predefiniti vengono usati se si chiamano i StringBuilder() costruttori e StringBuilder(String) .
È possibile definire in modo esplicito la capacità iniziale di un StringBuilder oggetto nei modi seguenti:
- Chiamando uno dei StringBuilder costruttori che include un
capacity
parametro quando si crea l'oggetto . - Assegnando in modo esplicito un nuovo valore alla StringBuilder.Capacity proprietà per espandere un oggetto esistente StringBuilder . La proprietà genera un'eccezione se la nuova capacità è minore della capacità esistente o maggiore della StringBuilder capacità massima dell'oggetto.
- Chiamando il StringBuilder.EnsureCapacity metodo con la nuova capacità. La nuova capacità non deve essere maggiore della StringBuilder capacità massima dell'oggetto. Tuttavia, a differenza di un'assegnazione alla Capacity proprietà, EnsureCapacity non genera un'eccezione se la nuova capacità desiderata è minore della capacità esistente. In questo caso, la chiamata al metodo non ha alcun effetto.
Se la lunghezza della stringa assegnata all'oggetto StringBuilder nella chiamata al costruttore supera la capacità predefinita o la capacità specificata, la Capacity proprietà viene impostata sulla lunghezza della stringa specificata con il value
parametro .
È possibile definire in modo esplicito la capacità massima di un StringBuilder oggetto chiamando il StringBuilder(Int32, Int32) costruttore . Non è possibile modificare la capacità massima assegnando un nuovo valore alla MaxCapacity proprietà, perché è di sola lettura.
Come illustrato nella sezione precedente, ogni volta che la capacità esistente è inadeguata, viene allocata memoria aggiuntiva e la capacità di un StringBuilder oggetto raddoppia fino al valore definito dalla MaxCapacity proprietà .
In generale, la capacità predefinita e la capacità massima sono adeguate per la maggior parte delle app. È possibile impostare questi valori nelle condizioni seguenti:
- Se è probabile che la dimensione finale dell'oggetto StringBuilder cresca in modo eccessivamente elevato, in genere in eccesso di diversi megabyte. In questo caso, potrebbe esserci un certo vantaggio dalle prestazioni dell'impostazione della proprietà iniziale Capacity su un valore significativamente elevato per eliminare la necessità di troppi riallocamenti di memoria.
- Se il codice è in esecuzione in un sistema con memoria limitata. In questo caso, è possibile impostare la MaxCapacity proprietà su minore di Int32.MaxValue se il codice gestisce stringhe di grandi dimensioni che potrebbero causare l'esecuzione in un ambiente con vincoli di memoria.
Creare un'istanza di un oggetto StringBuilder
Per creare un'istanza di un StringBuilder oggetto, chiamare uno dei sei costruttori di classi di overload elencati nella tabella seguente. Tre dei costruttori creano un'istanza di un StringBuilder oggetto il cui valore è una stringa vuota, ma imposta i relativi Capacity valori e MaxCapacity in modo diverso. I tre costruttori rimanenti definiscono un StringBuilder oggetto con un valore stringa e una capacità specifici. Due dei tre costruttori usano la capacità massima predefinita di Int32.MaxValue, mentre la terza consente di impostare la capacità massima.
Costruttore | Valore stringa | Capacità | Capacità massima |
---|---|---|---|
StringBuilder() | String.Empty | 16 | Int32.MaxValue |
StringBuilder(Int32) | String.Empty | Definito dal capacity parametro |
Int32.MaxValue |
StringBuilder(Int32, Int32) | String.Empty | Definito dal capacity parametro |
Definito dal maxCapacity parametro |
StringBuilder(String) | Definito dal value parametro |
16 o value . Length, indipendentemente dal fatto che sia maggiore |
Int32.MaxValue |
StringBuilder(String, Int32) | Definito dal value parametro |
Definito dal capacity parametro o value . Length, indipendentemente dal fatto che sia maggiore. |
Int32.MaxValue |
StringBuilder(String, Int32, Int32, Int32) | definito da value . Substring(startIndex , length ) |
Definito dal capacity parametro o value . Length, indipendentemente dal fatto che sia maggiore. |
Int32.MaxValue |
Nell'esempio seguente vengono usati tre di questi overload del costruttore per creare un'istanza di StringBuilder oggetti.
using System;
using System.Text;
public class Example8
{
public static void Main()
{
string value = "An ordinary string";
int index = value.IndexOf("An ") + 3;
int capacity = 0xFFFF;
// Instantiate a StringBuilder from a string.
StringBuilder sb1 = new StringBuilder(value);
ShowSBInfo(sb1);
// Instantiate a StringBuilder from string and define a capacity.
StringBuilder sb2 = new StringBuilder(value, capacity);
ShowSBInfo(sb2);
// Instantiate a StringBuilder from substring and define a capacity.
StringBuilder sb3 = new StringBuilder(value, index,
value.Length - index,
capacity);
ShowSBInfo(sb3);
}
public static void ShowSBInfo(StringBuilder sb)
{
Console.WriteLine("\nValue: {0}", sb.ToString());
foreach (var prop in sb.GetType().GetProperties())
{
if (prop.GetIndexParameters().Length == 0)
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
}
Console.WriteLine();
}
}
// The example displays the following output:
// Value: An ordinary string
// Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18
//
// Value: An ordinary string
// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18
//
// Value: ordinary string
// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15
open System.Text
let showSBInfo (sb: StringBuilder) =
for prop in sb.GetType().GetProperties() do
if prop.GetIndexParameters().Length = 0 then
printf $"{prop.Name}: {prop.GetValue sb:N0} "
printfn ""
let value = "An ordinary string"
let index = value.IndexOf "An " + 3
let capacity = 0xFFFF
// Instantiate a StringBuilder from a string.
let sb1 = StringBuilder value
showSBInfo sb1
// Instantiate a StringBuilder from string and define a capacity.
let sb2 = StringBuilder(value, capacity)
showSBInfo sb2
// Instantiate a StringBuilder from substring and define a capacity.
let sb3 = StringBuilder(value, index, value.Length - index, capacity)
showSBInfo sb3
// The example displays the following output:
// Value: An ordinary string
// Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18
//
// Value: An ordinary string
// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18
//
// Value: ordinary string
// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15
Imports System.Text
Module Example8
Public Sub Main()
Dim value As String = "An ordinary string"
Dim index As Integer = value.IndexOf("An ") + 3
Dim capacity As Integer = &HFFFF
' Instantiate a StringBuilder from a string.
Dim sb1 As New StringBuilder(value)
ShowSBInfo(sb1)
' Instantiate a StringBuilder from string and define a capacity.
Dim sb2 As New StringBuilder(value, capacity)
ShowSBInfo(sb2)
' Instantiate a StringBuilder from substring and define a capacity.
Dim sb3 As New StringBuilder(value, index,
value.Length - index,
capacity)
ShowSBInfo(sb3)
End Sub
Public Sub ShowSBInfo(sb As StringBuilder)
Console.WriteLine()
Console.WriteLine("Value: {0}", sb.ToString())
For Each prop In sb.GetType().GetProperties
If prop.GetIndexParameters().Length = 0 Then
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
End If
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' Value: An ordinary string
' Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18
'
' Value: An ordinary string
' Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18
'
' Value: ordinary string
' Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15
Chiamare i metodi StringBuilder
La maggior parte dei metodi che modificano la stringa in un'istanza StringBuilder restituisce un riferimento alla stessa istanza. In questo modo è possibile chiamare StringBuilder i metodi in due modi:
È possibile effettuare chiamate a singoli metodi e ignorare il valore restituito, come illustrato nell'esempio seguente.
using System; using System.Text; public class Example { public static void Main() { StringBuilder sb = new StringBuilder(); sb.Append("This is the beginning of a sentence, "); sb.Replace("the beginning of ", ""); sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete "); sb.Replace(",", "."); Console.WriteLine(sb.ToString()); } } // The example displays the following output: // This is a complete sentence.
open System.Text let sb = StringBuilder() sb.Append "This is the beginning of a sentence, " |> ignore sb.Replace("the beginning of ", "") |> ignore sb.Insert((string sb).IndexOf "a " + 2, "complete ") |> ignore sb.Replace(",", ".") |> ignore printfn $"{sb}" // The example displays the following output: // This is a complete sentence.
Imports System.Text Module Example2 Public Sub Main() Dim sb As New StringBuilder() sb.Append("This is the beginning of a sentence, ") sb.Replace("the beginning of ", "") sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ") sb.Replace(",", ".") Console.WriteLine(sb.ToString()) End Sub End Module ' The example displays the following output: ' This is a complete sentence.
È possibile effettuare una serie di chiamate al metodo in una singola istruzione. Ciò può essere utile se si vuole scrivere una singola istruzione che concatena le operazioni successive. Nell'esempio seguente vengono consolidate tre chiamate al metodo dell'esempio precedente in una singola riga di codice.
using System; using System.Text; public class Example2 { public static void Main() { StringBuilder sb = new StringBuilder("This is the beginning of a sentence, "); sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, "complete ").Replace(",", "."); Console.WriteLine(sb.ToString()); } } // The example displays the following output: // This is a complete sentence.
open System.Text let sb = StringBuilder "This is the beginning of a sentence, " sb .Replace("the beginning of ", "") .Insert((string sb).IndexOf "a " + 2, "complete ") .Replace(",", ".") |> ignore printfn $"{sb}" // The example displays the following output: // This is a complete sentence.
Imports System.Text Module Example3 Public Sub Main() Dim sb As New StringBuilder("This is the beginning of a sentence, ") sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, "complete ").Replace(", ", ".") Console.WriteLine(sb.ToString()) End Sub End Module ' The example displays the following output: ' This is a complete sentence.
Eseguire operazioni di StringBuilder
È possibile utilizzare i metodi della StringBuilder classe per scorrere, aggiungere, eliminare o modificare caratteri in un StringBuilder oggetto .
Iterate StringBuilder characters (Iterate StringBuilder characters)
È possibile accedere ai caratteri in un StringBuilder oggetto usando la StringBuilder.Chars[] proprietà . In C# Chars[] è un indicizzatore. In Visual Basic è la proprietà predefinita della StringBuilder classe . In questo modo è possibile impostare o recuperare singoli caratteri usando solo l'indice, senza fare riferimento in modo esplicito alla Chars[] proprietà . I caratteri in un StringBuilder oggetto iniziano in corrispondenza dell'indice 0 (zero) e continuano a indicizzare Length - 1.
Nell'esempio seguente viene illustrata la Chars[] proprietà . Aggiunge dieci numeri casuali a un StringBuilder oggetto e quindi esegue l'iterazione di ogni carattere. Se la categoria Unicode del carattere è UnicodeCategory.DecimalDigitNumber, diminuisce il numero di 1 (o imposta il numero su 9 se il valore è 0). Nell'esempio viene visualizzato il contenuto dell'oggetto StringBuilder sia prima che dopo la modifica dei valori dei singoli caratteri.
using System;
using System.Globalization;
using System.Text;
public class Example3
{
public static void Main()
{
Random rnd = new Random();
StringBuilder sb = new StringBuilder();
// Generate 10 random numbers and store them in a StringBuilder.
for (int ctr = 0; ctr <= 9; ctr++)
sb.Append(rnd.Next().ToString("N5"));
Console.WriteLine("The original string:");
Console.WriteLine(sb.ToString());
// Decrease each number by one.
for (int ctr = 0; ctr < sb.Length; ctr++)
{
if (Char.GetUnicodeCategory(sb[ctr]) == UnicodeCategory.DecimalDigitNumber)
{
int number = (int)Char.GetNumericValue(sb[ctr]);
number--;
if (number < 0) number = 9;
sb[ctr] = number.ToString()[0];
}
}
Console.WriteLine("\nThe new string:");
Console.WriteLine(sb.ToString());
}
}
// The example displays the following output:
// The original string:
// 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
// 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
// .00000
//
// The new string:
// 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
// 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
// .99999
open System
open System.Globalization
open System.Text
let rnd = Random()
let sb = new StringBuilder()
// Generate 10 random numbers and store them in a StringBuilder.
for _ = 0 to 9 do
rnd.Next().ToString "N5" |> sb.Append |> ignore
printfn "The original string:"
printfn $"{sb}"
// Decrease each number by one.
for i = 0 to sb.Length - 1 do
if Char.GetUnicodeCategory(sb[i]) = UnicodeCategory.DecimalDigitNumber then
let number = Char.GetNumericValue sb.[i] |> int
let number = number - 1
let number = if number < 0 then 9 else number
sb.[i] <- number.ToString()[0]
printfn "\nThe new string:"
printfn $"{sb}"
// The example displays the following output:
// The original string:
// 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
// 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
// .00000
//
// The new string:
// 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
// 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
// .99999
Imports System.Globalization
Imports System.Text
Module Example4
Public Sub Main()
Dim rnd As New Random()
Dim sb As New StringBuilder()
' Generate 10 random numbers and store them in a StringBuilder.
For ctr As Integer = 0 To 9
sb.Append(rnd.Next().ToString("N5"))
Next
Console.WriteLine("The original string:")
Console.WriteLine(sb.ToString())
Console.WriteLine()
' Decrease each number by one.
For ctr As Integer = 0 To sb.Length - 1
If Char.GetUnicodeCategory(sb(ctr)) = UnicodeCategory.DecimalDigitNumber Then
Dim number As Integer = CType(Char.GetNumericValue(sb(ctr)), Integer)
number -= 1
If number < 0 Then number = 9
sb(ctr) = number.ToString()(0)
End If
Next
Console.WriteLine("The new string:")
Console.WriteLine(sb.ToString())
End Sub
End Module
' The example displays the following output:
' The original string:
' 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
' 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
' .00000
'
' The new string:
' 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
' 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
' .99999
L'uso dell'indicizzazione basata sui caratteri con la proprietà Chars[] può essere lentissimo nelle condizioni seguenti:
- L'istanza StringBuilder è di grandi dimensioni (ad esempio, è costituita da diverse decine di migliaia di caratteri).
- è StringBuilder "in blocchi". Ovvero, le chiamate ripetute ai metodi, ad StringBuilder.Append esempio, hanno espanso automaticamente la proprietà dell'oggetto StringBuilder.Capacity e allocato nuovi blocchi di memoria.
L'impatto sulle prestazioni è notevole poiché ogni accesso ai caratteri scorre l'intero elenco di blocchi collegato per trovare il buffer corretto in cui eseguire l'indicizzazione.
Nota
Anche per un oggetto "in blocchi" StringBuilder di grandi dimensioni, l'uso della Chars[] proprietà per l'accesso basato su indice a uno o un numero ridotto di caratteri ha un impatto trascurabile sulle prestazioni. In genere, si tratta di un'operazione O(n). L'impatto significativo sulle prestazioni si verifica durante l'iterazione dei caratteri nell'oggetto StringBuilder, che è un'operazione O(n^2).
Se si verificano problemi di prestazioni quando si usa l'indicizzazione basata su caratteri con gli oggetti StringBuilder, è possibile adottare una delle seguenti soluzioni alternative:
Convertire l'istanza StringBuilder in un String chiamando il metodo ToString, quindi accedere ai caratteri nella stringa.
Copiare il contenuto dell'oggetto StringBuilder esistente in un nuovo oggetto StringBuilder con dimensioni preimpostate. Le prestazioni migliorano perché il nuovo oggetto StringBuilder non è pesante. Ad esempio:
// sbOriginal is the existing StringBuilder object var sbNew = new StringBuilder(sbOriginal.ToString(), sbOriginal.Length);
' sbOriginal is the existing StringBuilder object Dim sbNew = New StringBuilder(sbOriginal.ToString(), sbOriginal.Length)
Impostare la capacità iniziale dell'oggetto StringBuilder su un valore approssimativamente uguale alle dimensioni massime previste chiamando il costruttore StringBuilder(Int32). Si noti che in questo modo viene allocato l'intero di memoria anche se StringBuilder raramente raggiunge la capacità massima.
Aggiungere testo a un oggetto StringBuilder
La StringBuilder classe include i metodi seguenti per espandere il contenuto di un StringBuilder oggetto :
Il Append metodo aggiunge più volte una stringa, una sottostringa, una matrice di caratteri, una parte di una matrice di caratteri, un singolo carattere ripetuto più volte o la rappresentazione di stringa di un tipo di dati primitivo a un StringBuilder oggetto .
Il AppendLine metodo aggiunge un terminatore di riga o una stringa insieme a un terminatore di riga a un StringBuilder oggetto .
Il AppendFormat metodo aggiunge una stringa di formato composita a un StringBuilder oggetto . Le rappresentazioni di stringa degli oggetti inclusi nella stringa di risultato possono riflettere le convenzioni di formattazione delle impostazioni cultura di sistema correnti o delle impostazioni cultura specificate.
Il Insert metodo inserisce una stringa, una sottostringa, più ripetizioni di una stringa, una matrice di caratteri, una parte di una matrice di caratteri o la rappresentazione di stringa di un tipo di dati primitivo in una posizione specificata nell'oggetto StringBuilder . La posizione è definita da un indice in base zero.
Nell'esempio seguente vengono utilizzati i Appendmetodi , AppendLineAppendFormat, e Insert per espandere il testo di un StringBuilder oggetto .
using System;
using System.Text;
public class Example6
{
public static void Main()
{
// Create a StringBuilder object with no text.
StringBuilder sb = new StringBuilder();
// Append some text.
sb.Append('*', 10).Append(" Adding Text to a StringBuilder Object ").Append('*', 10);
sb.AppendLine("\n");
sb.AppendLine("Some code points and their corresponding characters:");
// Append some formatted text.
for (int ctr = 50; ctr <= 60; ctr++)
{
sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr));
sb.AppendLine();
}
// Find the end of the introduction to the column.
int pos = sb.ToString().IndexOf("characters:") + 11 +
Environment.NewLine.Length;
// Insert a column header.
sb.Insert(pos, String.Format("{2}{0,12:X4} {1,12}{2}", "Code Unit",
"Character", "\n"));
// Convert the StringBuilder to a string and display it.
Console.WriteLine(sb.ToString());
}
}
// The example displays the following output:
// ********** Adding Text to a StringBuilder Object **********
//
// Some code points and their corresponding characters:
//
// Code Unit Character
// 0032 2
// 0033 3
// 0034 4
// 0035 5
// 0036 6
// 0037 7
// 0038 8
// 0039 9
// 003A :
// 003B ;
// 003C <
open System
open System.Text
// Create a StringBuilder object with no text.
let sb = StringBuilder()
// Append some text.
sb
.Append('*', 10)
.Append(" Adding Text to a StringBuilder Object ")
.Append('*', 10)
|> ignore
sb.AppendLine "\n" |> ignore
sb.AppendLine "Some code points and their corresponding characters:" |> ignore
// Append some formatted text.
for i = 50 to 60 do
sb.AppendFormat("{0,12:X4} {1,12}", i, Convert.ToChar i) |> ignore
sb.AppendLine() |> ignore
// Find the end of the introduction to the column.
let pos = (string sb).IndexOf("characters:") + 11 + Environment.NewLine.Length
// Insert a column header.
sb.Insert(pos, String.Format("{2}{0,12:X4} {1,12}{2}", "Code Unit", "Character", "\n"))
|> ignore
// Convert the StringBuilder to a string and display it.
printfn $"{sb}"
// The example displays the following output:
// ********** Adding Text to a StringBuilder Object **********
//
// Some code points and their corresponding characters:
//
// Code Unit Character
// 0032 2
// 0033 3
// 0034 4
// 0035 5
// 0036 6
// 0037 7
// 0038 8
// 0039 9
// 003A :
// 003B ;
// 003C <
Imports System.Text
Module Example7
Public Sub Main()
' Create a StringBuilder object with no text.
Dim sb As New StringBuilder()
' Append some text.
sb.Append("*"c, 10).Append(" Adding Text to a StringBuilder Object ").Append("*"c, 10)
sb.AppendLine()
sb.AppendLine()
sb.AppendLine("Some code points and their corresponding characters:")
' Append some formatted text.
For ctr = 50 To 60
sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr))
sb.AppendLine()
Next
' Find the end of the introduction to the column.
Dim pos As Integer = sb.ToString().IndexOf("characters:") + 11 +
Environment.NewLine.Length
' Insert a column header.
sb.Insert(pos, String.Format("{2}{0,12:X4} {1,12}{2}", "Code Unit",
"Character", vbCrLf))
' Convert the StringBuilder to a string and display it.
Console.WriteLine(sb.ToString())
End Sub
End Module
' The example displays the following output:
' ********** Adding Text to a StringBuilder Object **********
'
' Some code points and their corresponding characters:
'
' Code Unit Character
' 0032 2
' 0033 3
' 0034 4
' 0035 5
' 0036 6
' 0037 7
' 0038 8
' 0039 9
' 003A :
' 003B ;
' 003C <
Eliminare testo da un oggetto StringBuilder
La StringBuilder classe include metodi che possono ridurre le dimensioni dell'istanza corrente StringBuilder . Il Clear metodo rimuove tutti i caratteri e imposta la Length proprietà su zero. Il Remove metodo elimina un numero specificato di caratteri a partire da una determinata posizione di indice. Inoltre, è possibile rimuovere caratteri dalla fine di un StringBuilder oggetto impostando la relativa Length proprietà su un valore minore della lunghezza dell'istanza corrente.
Nell'esempio seguente viene rimosso parte del testo da un StringBuilder oggetto , viene visualizzata la capacità risultante, la capacità massima e i valori delle proprietà length e quindi viene chiamato il Clear metodo per rimuovere tutti i caratteri dall'oggetto StringBuilder .
using System;
using System.Text;
public class Example5
{
public static void Main()
{
StringBuilder sb = new StringBuilder("A StringBuilder object");
ShowSBInfo(sb);
// Remove "object" from the text.
string textToRemove = "object";
int pos = sb.ToString().IndexOf(textToRemove);
if (pos >= 0)
{
sb.Remove(pos, textToRemove.Length);
ShowSBInfo(sb);
}
// Clear the StringBuilder contents.
sb.Clear();
ShowSBInfo(sb);
}
public static void ShowSBInfo(StringBuilder sb)
{
Console.WriteLine("\nValue: {0}", sb.ToString());
foreach (var prop in sb.GetType().GetProperties())
{
if (prop.GetIndexParameters().Length == 0)
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
}
Console.WriteLine();
}
}
// The example displays the following output:
// Value: A StringBuilder object
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
//
// Value: A StringBuilder
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
//
// Value:
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
open System.Text
let showSBInfo (sb: StringBuilder) =
for prop in sb.GetType().GetProperties() do
if prop.GetIndexParameters().Length = 0 then
printf $"{prop.Name}: {prop.GetValue sb:N0} "
printfn ""
let sb = StringBuilder "A StringBuilder object"
showSBInfo sb
// Remove "object" from the text.
let textToRemove = "object"
let pos = (string sb).IndexOf textToRemove
if pos >= 0 then
sb.Remove(pos, textToRemove.Length) |> ignore
showSBInfo sb
// Clear the StringBuilder contents.
sb.Clear() |> ignore
showSBInfo sb
// The example displays the following output:
// Value: A StringBuilder object
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
//
// Value: A StringBuilder
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
//
// Value:
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
Imports System.Text
Module Example6
Public Sub Main()
Dim sb As New StringBuilder("A StringBuilder object")
ShowSBInfo(sb)
' Remove "object" from the text.
Dim textToRemove As String = "object"
Dim pos As Integer = sb.ToString().IndexOf(textToRemove)
If pos >= 0 Then
sb.Remove(pos, textToRemove.Length)
ShowSBInfo(sb)
End If
' Clear the StringBuilder contents.
sb.Clear()
ShowSBInfo(sb)
End Sub
Public Sub ShowSBInfo(sb As StringBuilder)
Console.WriteLine()
Console.WriteLine("Value: {0}", sb.ToString())
For Each prop In sb.GetType().GetProperties
If prop.GetIndexParameters().Length = 0 Then
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
End If
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' Value: A StringBuilder object
' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
'
' Value: A StringBuilder
' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
'
' Value:
' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
Modificare il testo in un oggetto StringBuilder
Il StringBuilder.Replace metodo sostituisce tutte le occorrenze di un carattere o di una stringa nell'intero StringBuilder oggetto o in un intervallo di caratteri specifico. Nell'esempio seguente viene utilizzato il Replace metodo per sostituire tutti i punti esclamativi (!) con punti interrogativi (?) nell'oggetto StringBuilder .
using System;
using System.Text;
public class Example13
{
public static void Main()
{
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Replace('!', '?');
Console.WriteLine(MyStringBuilder);
}
}
// The example displays the following output:
// Hello World?
open System.Text
let myStringBuilder = StringBuilder "Hello World!"
myStringBuilder.Replace('!', '?') |> ignore
printfn $"{myStringBuilder}"
// The example displays the following output:
// Hello World?
Imports System.Text
Module Example
Public Sub Main()
Dim MyStringBuilder As New StringBuilder("Hello World!")
MyStringBuilder.Replace("!"c, "?"c)
Console.WriteLine(MyStringBuilder)
End Sub
End Module
' The example displays the following output:
' Hello World?
Cercare il testo in un oggetto StringBuilder
La StringBuilder classe non include metodi simili ai String.Containsmetodi , String.IndexOfe String.StartsWith forniti dalla String classe , che consentono di cercare un carattere specifico o una sottostringa nell'oggetto. Per determinare la presenza o la posizione iniziale del carattere di una sottostringa, è necessario cercare un String valore usando un metodo di ricerca di stringhe o un metodo di espressione regolare. Esistono quattro modi per implementare tali ricerche, come illustrato nella tabella seguente.
Tecnica | Vantaggi | Svantaggi |
---|---|---|
Cercare i valori stringa prima di aggiungerli all'oggetto StringBuilder . | Utile per determinare se esiste una sottostringa. | Non può essere utilizzato quando la posizione di indice di una sottostringa è importante. |
Chiamare ToString e cercare l'oggetto restituito String . | Facile da usare se si assegna tutto il testo a un StringBuilder oggetto e quindi iniziare a modificarlo. | Complessa da chiamare ToString ripetutamente se è necessario apportare modifiche prima che tutto il testo venga aggiunto all'oggetto StringBuilder . È necessario ricordare di lavorare dalla fine del StringBuilder testo dell'oggetto se si apportano modifiche. |
Utilizzare la Chars[] proprietà per cercare in sequenza un intervallo di caratteri. | Utile se si è interessati a singoli caratteri o a una piccola sottostringa. | Complesso se il numero di caratteri da cercare è elevato o se la logica di ricerca è complessa. Si ottengono prestazioni molto scarse per gli oggetti che sono cresciuti molto grandi tramite chiamate di metodo ripetute. |
Convertire l'oggetto StringBuilder in un String oggetto ed eseguire modifiche sull'oggetto String . | Utile se il numero di modifiche è ridotto. | Nega il vantaggio delle prestazioni della StringBuilder classe se il numero di modifiche è elevato. |
Esaminiamo queste tecniche in modo più dettagliato.
Se l'obiettivo della ricerca è determinare se esiste una particolare sottostringa, ovvero se non si è interessati alla posizione della sottostringa, è possibile cercare le stringhe prima di archiviarle nell'oggetto StringBuilder . Nell'esempio seguente viene fornita una possibile implementazione. Definisce una
StringBuilderFinder
classe il cui costruttore viene passato a un riferimento a un StringBuilder oggetto e alla sottostringa da trovare nella stringa. In questo caso, l'esempio tenta di determinare se le temperature registrate sono in Fahrenheit o Celsius e aggiunge il testo introduttivo appropriato all'inizio dell'oggetto StringBuilder . Un generatore di numeri casuali viene usato per selezionare una matrice che contiene dati in gradi Celsius o gradi Fahrenheit.using System; using System.Text; public class Example9 { public static void Main() { Random rnd = new Random(); string[] tempF = { "47.6F", "51.3F", "49.5F", "62.3F" }; string[] tempC = { "21.2C", "16.1C", "23.5C", "22.9C" }; string[][] temps = { tempF, tempC }; StringBuilder sb = new StringBuilder(); var f = new StringBuilderFinder(sb, "F"); var baseDate = new DateTime(2013, 5, 1); String[] temperatures = temps[rnd.Next(2)]; bool isFahrenheit = false; foreach (var temperature in temperatures) { if (isFahrenheit) sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature); else isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}\n", baseDate, temperature)); baseDate = baseDate.AddDays(1); } if (isFahrenheit) { sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit"); sb.Insert(47, "\n\n"); } else { sb.Insert(0, "Average Daily Temperature in Degrees Celsius"); sb.Insert(44, "\n\n"); } Console.WriteLine(sb.ToString()); } } public class StringBuilderFinder { private StringBuilder sb; private String text; public StringBuilderFinder(StringBuilder sb, String textToFind) { this.sb = sb; this.text = textToFind; } public bool SearchAndAppend(String stringToSearch) { sb.Append(stringToSearch); return stringToSearch.Contains(text); } } // The example displays output similar to the following: // Average Daily Temperature in Degrees Celsius // // 5/1/2013: 21.2C // 5/2/2013: 16.1C // 5/3/2013: 23.5C // 5/4/2013: 22.9C
open System open System.Text type StringBuilderFinder(sb: StringBuilder, textToFind: string) = member _.SearchAndAppend(stringToSearch: string) = sb.Append stringToSearch |> ignore stringToSearch.Contains textToFind let tempF = [| "47.6F"; "51.3F"; "49.5F"; "62.3F" |] let tempC = [| "21.2C"; "16.1C"; "23.5C"; "22.9C" |] let temps = [| tempF; tempC |] let sb = StringBuilder() let f = StringBuilderFinder(sb, "F") let temperatures = temps[Random.Shared.Next(2)] let mutable baseDate = DateTime(2013, 5, 1) let mutable isFahrenheit = false for temperature in temperatures do if isFahrenheit then sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature) |> ignore else isFahrenheit <- $"{baseDate:d}: {temperature}\n" |> f.SearchAndAppend baseDate <- baseDate.AddDays 1 if isFahrenheit then sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit") |> ignore sb.Insert(47, "\n\n") |> ignore else sb.Insert(0, "Average Daily Temperature in Degrees Celsius") |> ignore sb.Insert(44, "\n\n") |> ignore printfn $"{sb}" // The example displays output similar to the following: // Average Daily Temperature in Degrees Celsius // // 5/1/2013: 21.2C // 5/2/2013: 16.1C // 5/3/2013: 23.5C // 5/4/2013: 22.9C
Imports System.Text Module Example9 Public Sub Main() Dim rnd As New Random() Dim tempF() As String = {"47.6F", "51.3F", "49.5F", "62.3F"} Dim tempC() As String = {"21.2C", "16.1C", "23.5C", "22.9C"} Dim temps()() As String = {tempF, tempC} Dim sb As StringBuilder = New StringBuilder() Dim f As New StringBuilderFinder(sb, "F") Dim baseDate As New DateTime(2013, 5, 1) Dim temperatures() As String = temps(rnd.Next(2)) Dim isFahrenheit As Boolean = False For Each temperature In temperatures If isFahrenheit Then sb.AppendFormat("{0:d}: {1}{2}", baseDate, temperature, vbCrLf) Else isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}{2}", baseDate, temperature, vbCrLf)) End If baseDate = baseDate.AddDays(1) Next If isFahrenheit Then sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit") sb.Insert(47, vbCrLf + vbCrLf) Else sb.Insert(0, "Average Daily Temperature in Degrees Celsius") sb.Insert(44, vbCrLf + vbCrLf) End If Console.WriteLine(sb.ToString()) End Sub End Module Public Class StringBuilderFinder Private sb As StringBuilder Private text As String Public Sub New(sb As StringBuilder, textToFind As String) Me.sb = sb text = textToFind End Sub Public Function SearchAndAppend(stringToSearch As String) As Boolean sb.Append(stringToSearch) Return stringToSearch.Contains(text) End Function End Class ' The example displays output similar to the following: ' Average Daily Temperature in Degrees Celsius ' ' 5/1/2013: 21.2C ' 5/2/2013: 16.1C ' 5/3/2013: 23.5C ' 5/4/2013: 22.9C
Chiamare il StringBuilder.ToString metodo per convertire l'oggetto StringBuilder in un String oggetto . È possibile eseguire ricerche nella stringa usando metodi come String.LastIndexOf o String.StartsWithoppure è possibile usare espressioni regolari e la Regex classe per cercare i criteri. Poiché entrambi gli StringBuilder oggetti e String usano la codifica UTF-16 per archiviare i caratteri, le posizioni di indice dei caratteri, le sottostringhe e le corrispondenze di espressioni regolari sono uguali in entrambi gli oggetti. In questo modo è possibile utilizzare StringBuilder i metodi per apportare modifiche nella stessa posizione in cui il testo viene trovato nell'oggetto String .
Nota
Se si adotta questo approccio, è necessario lavorare dalla fine dell'oggetto all'inizio StringBuilder in modo che non sia necessario convertire ripetutamente l'oggetto StringBuilder in una stringa.
Questo approccio viene illustrato nell'esempio seguente: Archivia quattro occorrenze di ogni lettera dell'alfabeto inglese in un StringBuilder oggetto . Converte quindi il testo in un String oggetto e usa un'espressione regolare per identificare la posizione iniziale di ogni sequenza di quattro caratteri. Infine, aggiunge un carattere di sottolineatura prima di ogni sequenza di quattro caratteri ad eccezione della prima sequenza e converte il primo carattere della sequenza in maiuscolo.
using System; using System.Text; using System.Text.RegularExpressions; public class Example10 { public static void Main() { // Create a StringBuilder object with 4 successive occurrences // of each character in the English alphabet. StringBuilder sb = new StringBuilder(); for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++) sb.Append(Convert.ToChar(ctr), 4); // Create a parallel string object. String sbString = sb.ToString(); // Determine where each new character sequence begins. String pattern = @"(\w)\1+"; MatchCollection matches = Regex.Matches(sbString, pattern); // Uppercase the first occurrence of the sequence, and separate it // from the previous sequence by an underscore character. for (int ctr = matches.Count - 1; ctr >= 0; ctr--) { Match m = matches[ctr]; sb[m.Index] = Char.ToUpper(sb[m.Index]); if (m.Index > 0) sb.Insert(m.Index, "_"); } // Display the resulting string. sbString = sb.ToString(); int line = 0; do { int nChars = line * 80 + 79 <= sbString.Length ? 80 : sbString.Length - line * 80; Console.WriteLine(sbString.Substring(line * 80, nChars)); line++; } while (line * 80 < sbString.Length); } } // The example displays the following output: // Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ // Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
open System open System.Text open System.Text.RegularExpressions // Create a StringBuilder object with 4 successive occurrences // of each character in the English alphabet. let sb = StringBuilder() for char in 'a' .. 'z' do sb.Append(char, 4) |> ignore // Create a parallel string object. let sbString = string sb // Determine where each new character sequence begins. let pattern = @"(\w)\1+" let matches = Regex.Matches(sbString, pattern) // Uppercase the first occurrence of the sequence, and separate it // from the previous sequence by an underscore character. for i = matches.Count - 1 downto 0 do let m = matches[i] sb[m.Index] <- Char.ToUpper sb[m.Index] if m.Index > 0 then sb.Insert(m.Index, "_") |> ignore // Display the resulting string. let sbString2 = string sb for line = 0 to (sbString2.Length - 1) / 80 do let nChars = if line * 80 + 79 <= sbString2.Length then 80 else sbString2.Length - line * 80 printfn $"{sbString2.Substring(line * 80, nChars)}" // The example displays the following output: // Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ // Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
Imports System.Text Imports System.Text.RegularExpressions Module Example10 Public Sub Main() ' Create a StringBuilder object with 4 successive occurrences ' of each character in the English alphabet. Dim sb As New StringBuilder() For ctr As UShort = AscW("a") To AscW("z") sb.Append(ChrW(ctr), 4) Next ' Create a parallel string object. Dim sbString As String = sb.ToString() ' Determine where each new character sequence begins. Dim pattern As String = "(\w)\1+" Dim matches As MatchCollection = Regex.Matches(sbString, pattern) ' Uppercase the first occurrence of the sequence, and separate it ' from the previous sequence by an underscore character. For ctr As Integer = matches.Count - 1 To 0 Step -1 Dim m As Match = matches(ctr) sb.Chars(m.Index) = Char.ToUpper(sb.Chars(m.Index)) If m.Index > 0 Then sb.Insert(m.Index, "_") Next ' Display the resulting string. sbString = sb.ToString() Dim line As Integer = 0 Do Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length, 80, sbString.Length - line * 80) Console.WriteLine(sbString.Substring(line * 80, nChars)) line += 1 Loop While line * 80 < sbString.Length End Sub End Module ' The example displays the following output: ' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ ' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
Utilizzare la StringBuilder.Chars[] proprietà per cercare in sequenza un intervallo di caratteri in un StringBuilder oggetto . Questo approccio potrebbe non essere pratico se il numero di caratteri da cercare è elevato o la logica di ricerca è particolarmente complessa. Per le implicazioni sulle prestazioni dell'accesso in base all'indice di caratteri per oggetti molto grandi e in blocchi StringBuilder , vedere la documentazione per la StringBuilder.Chars[] proprietà .
L'esempio seguente è identico alla funzionalità dell'esempio precedente, ma differisce nell'implementazione. Usa la Chars[] proprietà per rilevare quando un valore di carattere è stato modificato, inserisce un carattere di sottolineatura in tale posizione e converte il primo carattere nella nuova sequenza in maiuscolo.
using System; using System.Text; public class Example11 { public static void Main() { // Create a StringBuilder object with 4 successive occurrences // of each character in the English alphabet. StringBuilder sb = new StringBuilder(); for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++) sb.Append(Convert.ToChar(ctr), 4); // Iterate the text to determine when a new character sequence occurs. int position = 0; Char current = '\u0000'; do { if (sb[position] != current) { current = sb[position]; sb[position] = Char.ToUpper(sb[position]); if (position > 0) sb.Insert(position, "_"); position += 2; } else { position++; } } while (position <= sb.Length - 1); // Display the resulting string. String sbString = sb.ToString(); int line = 0; do { int nChars = line * 80 + 79 <= sbString.Length ? 80 : sbString.Length - line * 80; Console.WriteLine(sbString.Substring(line * 80, nChars)); line++; } while (line * 80 < sbString.Length); } } // The example displays the following output: // Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ // Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
open System open System.Text // Create a StringBuilder object with 4 successive occurrences // of each character in the English alphabet. let sb = StringBuilder() for char in 'a' .. 'z' do sb.Append(char, 4) |> ignore // Iterate the text to determine when a new character sequence occurs. let mutable position = 0 let mutable current = '\u0000' while position <= sb.Length - 1 do if sb[position] <> current then current <- sb[position] sb[position] <- Char.ToUpper sb[position] if position > 0 then sb.Insert(position, "_") |> ignore position <- position + 2 else position <- position + 1 // Display the resulting string. let sbString = string sb for line = 0 to (sbString.Length - 1) / 80 do let nChars = if line * 80 + 79 <= sbString.Length then 80 else sbString.Length - line * 80 printfn $"{sbString.Substring(line * 80, nChars)}" // The example displays the following output: // Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ // Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
Imports System.Text Module Example11 Public Sub Main() ' Create a StringBuilder object with 4 successive occurrences ' of each character in the English alphabet. Dim sb As New StringBuilder() For ctr As UShort = AscW("a") To AscW("z") sb.Append(ChrW(ctr), 4) Next ' Iterate the text to determine when a new character sequence occurs. Dim position As Integer = 0 Dim current As Char = ChrW(0) Do If sb(position) <> current Then current = sb(position) sb(position) = Char.ToUpper(sb(position)) If position > 0 Then sb.Insert(position, "_") position += 2 Else position += 1 End If Loop While position <= sb.Length - 1 ' Display the resulting string. Dim sbString As String = sb.ToString() Dim line As Integer = 0 Do Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length, 80, sbString.Length - line * 80) Console.WriteLine(sbString.Substring(line * 80, nChars)) line += 1 Loop While line * 80 < sbString.Length End Sub End Module ' The example displays the following output: ' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ ' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
Archiviare tutto il testo non modificato nell'oggetto StringBuilder , chiamare il StringBuilder.ToString metodo per convertire l'oggetto StringBuilder in un String oggetto ed eseguire le modifiche sull'oggetto String . È possibile usare questo approccio se sono presenti solo alcune modifiche; in caso contrario, il costo di utilizzo di stringhe non modificabili potrebbe negare i vantaggi delle prestazioni dell'uso di un StringBuilder oggetto .
L'esempio seguente è identico alle funzionalità dei due esempi precedenti, ma differisce nell'implementazione. Crea un StringBuilder oggetto, lo converte in un String oggetto e quindi usa un'espressione regolare per eseguire tutte le modifiche rimanenti sulla stringa. Il Regex.Replace(String, String, MatchEvaluator) metodo usa un'espressione lambda per eseguire la sostituzione in ogni corrispondenza.
using System; using System.Text; using System.Text.RegularExpressions; public class Example12 { public static void Main() { // Create a StringBuilder object with 4 successive occurrences // of each character in the English alphabet. StringBuilder sb = new StringBuilder(); for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++) sb.Append(Convert.ToChar(ctr), 4); // Convert it to a string. String sbString = sb.ToString(); // Use a regex to uppercase the first occurrence of the sequence, // and separate it from the previous sequence by an underscore. string pattern = @"(\w)(\1+)"; sbString = Regex.Replace(sbString, pattern, m => (m.Index > 0 ? "_" : "") + m.Groups[1].Value.ToUpper() + m.Groups[2].Value); // Display the resulting string. int line = 0; do { int nChars = line * 80 + 79 <= sbString.Length ? 80 : sbString.Length - line * 80; Console.WriteLine(sbString.Substring(line * 80, nChars)); line++; } while (line * 80 < sbString.Length); } } // The example displays the following output: // Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ // Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
open System.Text open System.Text.RegularExpressions // Create a StringBuilder object with 4 successive occurrences // of each character in the English alphabet. let sb = StringBuilder() for char in 'a' .. 'z' do sb.Append(char, 4) |> ignore // Convert it to a string. let sbString = string sb // Use a regex to uppercase the first occurrence of the sequence, // and separate it from the previous sequence by an underscore. let pattern = @"(\w)(\1+)" let sbStringReplaced = Regex.Replace( sbString, pattern, fun m -> (if m.Index > 0 then "_" else "") + m.Groups[ 1 ].Value.ToUpper() + m.Groups[2].Value ) // Display the resulting string. for line = 0 to (sbStringReplaced.Length - 1) / 80 do let nChars = if line * 80 + 79 <= sbStringReplaced.Length then 80 else sbStringReplaced.Length - line * 80 printfn $"{sbStringReplaced.Substring(line * 80, nChars)}" // The example displays the following output: // Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ // Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
Imports System.Text Imports System.Text.RegularExpressions Module Example12 Public Sub Main() ' Create a StringBuilder object with 4 successive occurrences ' of each character in the English alphabet. Dim sb As New StringBuilder() For ctr As UShort = AscW("a") To AscW("z") sb.Append(ChrW(ctr), 4) Next ' Convert it to a string. Dim sbString As String = sb.ToString() ' Use a regex to uppercase the first occurrence of the sequence, ' and separate it from the previous sequence by an underscore. Dim pattern As String = "(\w)(\1+)" sbString = Regex.Replace(sbString, pattern, Function(m) If(m.Index > 0, "_", "") + m.Groups(1).Value.ToUpper + m.Groups(2).Value) ' Display the resulting string. Dim line As Integer = 0 Do Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length, 80, sbString.Length - line * 80) Console.WriteLine(sbString.Substring(line * 80, nChars)) line += 1 Loop While line * 80 < sbString.Length End Sub End Module ' The example displays the following output: ' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ ' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
Convertire l'oggetto StringBuilder in una stringa
È necessario convertire l'oggetto StringBuilder in un oggetto String prima di poter passare la stringa rappresentata dall'oggetto StringBuilder a un metodo che contiene un parametro String o per visualizzarlo nell'interfaccia utente. Per eseguire questa conversione, chiamare il StringBuilder.ToString metodo . Per un'illustrazione, vedere l'esempio precedente, che chiama il ToString metodo per convertire un StringBuilder oggetto in una stringa in modo che possa essere passato a un metodo di espressione regolare.