Classe System.Text.StringBuilder
Este artigo fornece observações complementares à documentação de referência para essa API.
A StringBuilder classe representa um objeto semelhante a uma cadeia de caracteres cujo valor é uma sequência mutável de caracteres.
StringBuilder versus tipo de cadeia de caracteres
Embora StringBuilder ambos representem String sequências de caracteres, eles são implementados de forma diferente. String é um tipo imutável. Ou seja, cada operação que parece modificar um String objeto na verdade cria uma nova cadeia de caracteres.
Por exemplo, a chamada para o String.Concat método no exemplo de C# a seguir parece alterar o valor de uma variável de cadeia de caracteres chamada value
. Na verdade, o Concat método retorna um value
objeto que tem um valor e endereço diferentes do value
objeto que foi passado para o método. Observe que o exemplo deve ser compilado usando a opção do /unsafe
compilador.
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
Para rotinas que executam manipulação extensiva de cadeia de caracteres (como aplicativos que modificam uma cadeia de caracteres várias vezes em um loop), modificar uma cadeia de caracteres repetidamente pode exercer uma penalidade de desempenho significativa. A alternativa é usar StringBuilder, que é uma classe de string mutável. Mutabilidade significa que, uma vez que uma instância da classe tenha sido criada, ela pode ser modificada anexando, removendo, substituindo ou inserindo caracteres.
Importante
Embora a StringBuilder classe geralmente ofereça melhor desempenho do que a String classe, você não deve substituir String StringBuilder automaticamente por sempre que quiser manipular cadeias de caracteres. O desempenho depende do tamanho da cadeia de caracteres, da quantidade de memória a ser alocada para a nova cadeia de caracteres, do sistema no qual o código está sendo executado e do tipo de operação. Você deve estar preparado para testar seu código para determinar se StringBuilder realmente oferece uma melhoria significativa de desempenho.
Considere usar a String classe nestas condições:
- Quando o número de alterações que seu código fará em uma cadeia de caracteres é pequeno. Nesses casos, StringBuilder pode oferecer uma melhoria de desempenho insignificante ou nenhuma melhoria em relação ao .String
- Quando você executa um número fixo de operações de concatenação, especialmente com literais de cadeia de caracteres. Nesse caso, o compilador pode combinar as operações de concatenação em uma única operação.
- Quando você precisa executar operações de pesquisa extensas enquanto está construindo sua string. A StringBuilder classe não possui métodos de pesquisa como
IndexOf
ouStartsWith
. Você terá que converter o StringBuilder objeto em a String para essas operações, e isso pode anular o benefício de desempenho do uso StringBuilderdo . Para obter mais informações, consulte a seção Pesquisar o texto em um objeto StringBuilder.
Considere usar a StringBuilder classe nestas condições:
- Quando você espera que seu código faça um número desconhecido de alterações em uma cadeia de caracteres em tempo de design (por exemplo, quando você usa um loop para concatenar um número aleatório de cadeias de caracteres que contêm entrada do usuário).
- Quando você espera que seu código faça um número significativo de alterações em uma cadeia de caracteres.
Como StringBuilder funciona
A StringBuilder.Length propriedade indica o número de caracteres que o StringBuilder objeto contém no momento. Se você adicionar caracteres ao StringBuilder objeto, seu comprimento aumentará até ser igual ao StringBuilder.Capacity tamanho da propriedade, que define o número de caracteres que o objeto pode conter. Se o número de caracteres adicionados fizer com que o StringBuilder comprimento do objeto exceda sua capacidade atual, uma nova memória será alocada, o Capacity valor da propriedade será dobrado, novos caracteres serão adicionados ao StringBuilder objeto e sua Length propriedade será ajustada. A memória adicional para o StringBuilder objeto é alocada dinamicamente até atingir o valor definido pela StringBuilder.MaxCapacity propriedade. Quando a capacidade máxima é atingida, nenhuma memória adicional pode ser alocada para o StringBuilder objeto, e tentar adicionar caracteres ou expandi-lo além de sua capacidade máxima lança uma ArgumentOutOfRangeException ou uma OutOfMemoryException exceção.
O exemplo a seguir ilustra como um StringBuilder objeto aloca nova memória e aumenta sua capacidade dinamicamente à medida que a cadeia de caracteres atribuída ao objeto se expande. O código cria um StringBuilder objeto chamando seu construtor padrão (sem parâmetros). A capacidade padrão desse objeto é de 16 caracteres e sua capacidade máxima é de mais de 2 bilhões de caracteres. Acrescentar a cadeia de caracteres "Esta é uma frase." resulta em uma nova alocação de memória porque o comprimento da cadeia de caracteres (19 caracteres) excede a capacidade padrão do StringBuilder objeto. A capacidade do objeto dobra para 32 caracteres, a nova string é adicionada e o comprimento do objeto agora é igual a 19 caracteres. Em seguida, o código acrescenta a cadeia de caracteres "Esta é uma frase adicional." ao valor do StringBuilder objeto 11 vezes. Sempre que a operação de acréscimo faz com que o StringBuilder comprimento do objeto exceda sua capacidade, sua capacidade existente é dobrada e a Append operação é bem-sucedida.
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
Alocação de memória
A capacidade padrão de um StringBuilder objeto é de 16 caracteres e sua capacidade máxima padrão é Int32.MaxValue. Esses valores padrão serão usados se você chamar os StringBuilder() construtores and StringBuilder(String) .
Você pode definir explicitamente a capacidade inicial de um StringBuilder objeto das seguintes maneiras:
- Chamando qualquer um dos StringBuilder construtores que inclui um
capacity
parâmetro quando você cria o objeto. - Atribuindo explicitamente um novo valor à StringBuilder.Capacity propriedade para expandir um objeto existente StringBuilder . (A propriedade lançará uma exceção se a nova capacidade for menor que a capacidade existente ou maior que a StringBuilder capacidade máxima do objeto.)
- Chamando o StringBuilder.EnsureCapacity método com a nova capacidade. A nova capacidade não deve ser maior que a StringBuilder capacidade máxima do objeto. No entanto, ao contrário de uma atribuição à Capacity propriedade, EnsureCapacity não gera uma exceção se a nova capacidade desejada for menor que a capacidade existente. Nesse caso, a chamada de método não tem efeito.
Se o comprimento da cadeia de caracteres atribuída ao StringBuilder objeto na chamada do construtor exceder a capacidade padrão ou a capacidade especificada, a Capacity propriedade será definida como o comprimento da cadeia de caracteres especificada com o value
parâmetro.
Você pode definir explicitamente a capacidade máxima de um StringBuilder objeto chamando o StringBuilder(Int32, Int32) construtor. Você não pode alterar a capacidade máxima atribuindo um novo valor à MaxCapacity propriedade, pois ela é somente leitura.
Como mostra a seção anterior, sempre que a capacidade existente é inadequada, memória adicional é alocada e a capacidade de um StringBuilder objeto dobra até o valor definido pela MaxCapacity propriedade.
Em geral, a capacidade padrão e a capacidade máxima são adequadas para a maioria dos aplicativos. Você pode considerar definir esses valores nas seguintes condições:
- Se o tamanho final do StringBuilder objeto provavelmente crescerá excessivamente, normalmente acima de vários megabytes. Nesse caso, pode haver algum benefício de desempenho ao definir a propriedade inicial Capacity como um valor significativamente alto para eliminar a necessidade de muitas realocações de memória.
- Se o código estiver sendo executado em um sistema com memória limitada. Nesse caso, você pode considerar definir a MaxCapacity propriedade como menor do Int32.MaxValue que se o código estiver lidando com cadeias de caracteres grandes que podem fazer com que ele seja executado em um ambiente com restrição de memória.
Instanciar um objeto StringBuilder
Você instancia um StringBuilder objeto chamando um de seus seis construtores de classe sobrecarregados, que estão listados na tabela a seguir. Três dos construtores instanciam um StringBuilder objeto cujo valor é uma cadeia de caracteres vazia, mas definem seus Capacity valores e MaxCapacity de forma diferente. Os três construtores restantes definem um StringBuilder objeto que tem um valor de cadeia de caracteres e capacidade específicos. Dois dos três construtores usam a capacidade máxima padrão de Int32.MaxValue, enquanto o terceiro permite que você defina a capacidade máxima.
Construtor | Valor da cadeia de caracteres | Capacidade | Capacidade máxima |
---|---|---|---|
StringBuilder() | String.Empty | 16 | Int32.MaxValue |
StringBuilder(Int32) | String.Empty | Definido pelo capacity parâmetro |
Int32.MaxValue |
StringBuilder(Int32, Int32) | String.Empty | Definido pelo capacity parâmetro |
Definido pelo maxCapacity parâmetro |
StringBuilder(String) | Definido pelo value parâmetro |
16 ou value . Length, o que for maior |
Int32.MaxValue |
StringBuilder(String, Int32) | Definido pelo value parâmetro |
Definido pelo capacity parâmetro ou value . Length, o que for maior. |
Int32.MaxValue |
StringBuilder(String, Int32, Int32, Int32) | Definido por value . Substring(startIndex , length ) |
Definido pelo capacity parâmetro ou value . Length, o que for maior. |
Int32.MaxValue |
O exemplo a seguir usa três dessas sobrecargas de construtor para instanciar StringBuilder objetos.
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
Chamar métodos StringBuilder
A maioria dos métodos que modificam a cadeia de caracteres em uma StringBuilder instância retorna uma referência a essa mesma instância. Isso permite que você chame StringBuilder métodos de duas maneiras:
Você pode fazer chamadas de método individuais e ignorar o valor retornado, como faz o exemplo a seguir.
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.
Você pode fazer uma série de chamadas de método em uma única instrução. Isso pode ser conveniente se você quiser escrever uma única instrução que encadeie operações sucessivas. O exemplo a seguir consolida três chamadas de método do exemplo anterior em uma única linha de código.
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.
Executar operações do StringBuilder
Você pode usar os StringBuilder métodos da classe para iterar, adicionar, excluir ou modificar caracteres em um StringBuilder objeto.
Iterar caracteres StringBuilder
Você pode acessar os caracteres em um StringBuilder objeto usando a StringBuilder.Chars[] propriedade. Em C#, Chars[] é um indexador; no Visual Basic, é a propriedade padrão da StringBuilder classe. Isso permite que você defina ou recupere caracteres individuais usando apenas seu índice, sem referenciar explicitamente a Chars[] propriedade. Os caracteres em um StringBuilder objeto começam no índice 0 (zero) e continuam a indexar Length - 1.
O exemplo a seguir ilustra a Chars[] propriedade. Ele acrescenta dez números aleatórios a um StringBuilder objeto e, em seguida, itera cada caractere. Se a categoria Unicode do caractere for UnicodeCategory.DecimalDigitNumber, ele diminuirá o número em 1 (ou alterará o número para 9 se seu valor for 0). O exemplo exibe o StringBuilder conteúdo do objeto antes e depois que os valores de caracteres individuais foram alterados.
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
O uso da indexação baseada em caracteres com a propriedade Chars[] pode ser extremamente lento nas seguintes condições:
- A instância de StringBuilder é grande (por exemplo, ela consiste em várias dezenas de milhares de caracteres).
- O StringBuilder é "robusto". Ou seja, chamadas repetidas para métodos como StringBuilder.Append expandiram automaticamente a propriedade do StringBuilder.Capacity objeto e alocaram novos pedaços de memória para ele.
O desempenho é afetado gravemente porque cada acesso de caractere percorre toda a lista vinculada de partes para localizar o buffer correto ao qual indexar.
Observação
Mesmo para um objeto "chunky" StringBuilder grande, usar a Chars[] propriedade para acesso baseado em índice a um ou um pequeno número de caracteres tem um impacto insignificante no desempenho; normalmente, é uma operação O(n ). O impacto significativo sobre o desempenho ocorre ao iterar os caracteres no objeto StringBuilder, que é uma operação O(n^2).
Se encontrar problemas de desempenho ao usar a indexação baseada em caractere com objetos StringBuilder, você poderá usar qualquer uma das seguintes alternativas:
Converter a instância StringBuilder para um String chamando o método ToString e, em seguida, acessar os caracteres na cadeia de caracteres.
Copiar o conteúdo do objeto StringBuilder existente para um novo objeto StringBuilder pré-dimensionado. O desempenho melhora porque o novo objeto StringBuilder não é robusto. Por exemplo:
// 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)
Definir a capacidade inicial do objeto StringBuilder como um valor aproximadamente igual ao seu tamanho máximo esperado chamando o construtor StringBuilder(Int32). Observe que isso aloca o bloco de memória inteiro mesmo que o StringBuilder raramente atinja sua capacidade máxima.
Adicionar texto a um objeto StringBuilder
A StringBuilder classe inclui os seguintes métodos para expandir o conteúdo de um StringBuilder objeto:
O Append método acrescenta uma cadeia de caracteres, uma subcadeia de caracteres, uma matriz de caracteres, uma parte de uma matriz de caracteres, um único caractere repetido várias vezes ou a representação de cadeia de caracteres de um tipo de dados primitivo a um StringBuilder objeto.
O AppendLine método acrescenta um terminador de linha ou uma cadeia de caracteres junto com um terminador de linha a um StringBuilder objeto.
O AppendFormat método acrescenta uma cadeia de caracteres de formato composto a um StringBuilder objeto. As representações de cadeia de caracteres de objetos incluídos na cadeia de caracteres de resultado podem refletir as convenções de formatação da cultura do sistema atual ou de uma cultura especificada.
O Insert método insere uma cadeia de caracteres, uma subcadeia de caracteres, várias repetições de uma cadeia de caracteres, uma matriz de caracteres, uma parte de uma matriz de caracteres ou a representação de cadeia de caracteres de um tipo de dados primitivo em uma posição especificada no StringBuilder objeto. A posição é definida por um índice baseado em zero.
O exemplo a seguir usa os Appendmétodos , AppendLine, AppendFormate Insert para expandir o texto de um StringBuilder objeto.
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 <
Excluir texto de um objeto StringBuilder
A StringBuilder classe inclui métodos que podem reduzir o tamanho da instância atual StringBuilder . O Clear método remove todos os caracteres e define a Length propriedade como zero. O Remove método exclui um número especificado de caracteres começando em uma posição de índice específica. Além disso, você pode remover caracteres do final de um StringBuilder objeto definindo sua Length propriedade como um valor menor que o comprimento da instância atual.
O exemplo a seguir remove parte do texto de um StringBuilder objeto, exibe seus valores de propriedade de capacidade, capacidade máxima e comprimento resultantes e, em seguida, chama o Clear método para remover todos os caracteres do StringBuilder objeto.
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
Modificar o texto em um objeto StringBuilder
O StringBuilder.Replace método substitui todas as ocorrências de um caractere ou uma cadeia de caracteres em todo StringBuilder o objeto ou em um intervalo de caracteres específico. O exemplo a seguir usa o Replace método para substituir todos os pontos de exclamação (!) por pontos de interrogação (?) no StringBuilder objeto.
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?
Pesquisar o texto em um objeto StringBuilder
A StringBuilder classe não inclui métodos semelhantes aos String.Contains, String.IndexOf, e String.StartsWith métodos fornecidos pela String classe, que permitem pesquisar o objeto por um caractere específico ou uma substring. Determinar a presença ou a posição inicial do caractere de uma subcadeia de caracteres requer que você pesquise um String valor usando um método de pesquisa de cadeia de caracteres ou um método de expressão regular. Há quatro maneiras de implementar essas pesquisas, como mostra a tabela a seguir.
Técnica | Vantagens | Desvantagens |
---|---|---|
Pesquise valores de cadeia de caracteres antes de adicioná-los ao StringBuilder objeto. | Útil para determinar se existe uma subcadeia de caracteres. | Não pode ser usado quando a posição do índice de uma subcadeia de caracteres é importante. |
Chame ToString e pesquise o objeto retornado String . | Fácil de usar se você atribuir todo o texto a um StringBuilder objeto e começar a modificá-lo. | Complicado chamar ToString repetidamente se você precisar fazer modificações antes que todo o texto seja adicionado ao StringBuilder objeto. Você deve se lembrar de trabalhar a partir do final do texto do StringBuilder objeto se estiver fazendo alterações. |
Use a Chars[] propriedade para pesquisar sequencialmente um intervalo de caracteres. | Útil se você estiver preocupado com caracteres individuais ou uma pequena substring. | Complicado se o número de caracteres a serem pesquisados for grande ou se a lógica de pesquisa for complexa. Resulta em um desempenho muito ruim para objetos que cresceram muito por meio de chamadas de método repetidas. |
Converta o StringBuilder objeto em um String objeto e execute modificações no String objeto. | Útil se o número de modificações for pequeno. | Nega o benefício de desempenho da StringBuilder classe se o número de modificações for grande. |
Vamos examinar essas técnicas com mais detalhes.
Se o objetivo da pesquisa for determinar se existe uma subcadeia de caracteres específica (ou seja, se você não estiver interessado na posição da subcadeia de caracteres), poderá pesquisar cadeias de caracteres antes de armazená-las no StringBuilder objeto. O exemplo a seguir fornece uma implementação possível. Ele define uma
StringBuilderFinder
classe cujo construtor recebe uma referência a um StringBuilder objeto e a substring a ser encontrada na string. Nesse caso, o exemplo tenta determinar se as temperaturas registradas estão em Fahrenheit ou Celsius e adiciona o texto introdutório apropriado ao início do StringBuilder objeto. Um gerador de números aleatórios é usado para selecionar uma matriz que contém dados em graus Celsius ou graus 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
Chame o StringBuilder.ToString método para converter o StringBuilder objeto em um String objeto. Você pode pesquisar a cadeia de caracteres usando métodos como String.LastIndexOf ou String.StartsWith, ou pode usar expressões regulares e a Regex classe para pesquisar padrões. Como os StringBuilder objetos e String usam a codificação UTF-16 para armazenar caracteres, as posições de índice de caracteres, subcadeias de caracteres e correspondências de expressões regulares são as mesmas em ambos os objetos. Isso permite que você use StringBuilder métodos para fazer alterações na mesma posição em que esse String texto é encontrado no objeto.
Observação
Se você adotar essa abordagem, deverá trabalhar do final do objeto até o StringBuilder início para não precisar converter repetidamente o StringBuilder objeto em uma cadeia de caracteres.
O exemplo a seguir ilustra esta abordagem. Ele armazena quatro ocorrências de cada letra do alfabeto inglês em um StringBuilder objeto. Em seguida, ele converte o texto em um String objeto e usa uma expressão regular para identificar a posição inicial de cada sequência de quatro caracteres. Por fim, ele adiciona um sublinhado antes de cada sequência de quatro caracteres, exceto a primeira sequência, e converte o primeiro caractere da sequência em maiúsculas.
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
Use a StringBuilder.Chars[] propriedade para pesquisar sequencialmente um intervalo de caracteres em um StringBuilder objeto. Essa abordagem pode não ser prática se o número de caracteres a serem pesquisados for grande ou se a lógica de pesquisa for particularmente complexa. Para obter as implicações de desempenho do acesso baseado em índice caractere por caractere para objetos muito grandes e em StringBuilder partes, consulte a documentação da StringBuilder.Chars[] propriedade.
O exemplo a seguir é idêntico em funcionalidade ao exemplo anterior, mas difere na implementação. Ele usa a Chars[] propriedade para detectar quando um valor de caractere foi alterado, insere um sublinhado nessa posição e converte o primeiro caractere na nova sequência em maiúsculas.
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
Armazene todo o texto não modificado no StringBuilder objeto, chame o StringBuilder.ToString método para converter o StringBuilder objeto em um String objeto e execute as String modificações no objeto. Você pode usar essa abordagem se tiver apenas algumas modificações; caso contrário, o custo de trabalhar com cadeias de caracteres imutáveis pode anular os benefícios de desempenho do uso de um StringBuilder objeto.
O exemplo a seguir é idêntico em funcionalidade aos dois exemplos anteriores, mas difere na implementação. Ele cria um StringBuilder objeto, converte-o em um String objeto e, em seguida, usa uma expressão regular para executar todas as modificações restantes na cadeia de caracteres. O Regex.Replace(String, String, MatchEvaluator) método usa uma expressão lambda para executar a substituição em cada correspondência.
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
Converter o objeto StringBuilder em uma cadeia de caracteres
Você deve converter o objeto StringBuilder em um objeto Stringpara transmitir a cadeia de caracteres representada pelo objeto StringBuilder para um método que tem um parâmetro String ou exibi-lo na interface do usuário. Você executa essa conversão chamando o StringBuilder.ToString método. Para obter uma ilustração, consulte o exemplo anterior, que chama o ToString método para converter um StringBuilder objeto em uma cadeia de caracteres para que ele possa ser passado para um método de expressão regular.