Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Nota
Este artigo fornece observações complementares à documentação de referência para esta 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 String
Embora StringBuilder e String ambos representem 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 realmente cria uma nova cadeia de caracteres.
Por exemplo, a chamada para o String.Concat método no exemplo 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 /unsafe opção de 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 acrescentando, 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 automaticamente por StringBuilder 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. Nestes casos, StringBuilder pode oferecer uma melhoria de desempenho negligenciável ou nenhuma em relação ao String.
- Quando você executa um número fixo de operações de concatenação, particularmente com literais de cadeia de caracteres. Nesse caso, o compilador pode combinar as operações de concatenação em uma única operação.
- Quando precisas executar extensas operações de pesquisa enquanto estás a construir a tua string. A StringBuilder classe não possui métodos de pesquisa, como
IndexOfouStartsWith. Você terá que converter o objeto StringBuilder em um String para essas operações, o que pode negar o benefício de desempenho de usar StringBuilder. 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 funciona o StringBuilder
A StringBuilder.Length propriedade indica o número de caracteres que o StringBuilder objeto contém atualmente. Se você adicionar caracteres ao StringBuilder objeto, seu comprimento aumentará até ser igual ao tamanho da StringBuilder.Capacity 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, nova memória será alocada, o valor da Capacity 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 gera 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 deste objeto é de 16 caracteres e sua capacidade máxima é de mais de 2 bilhões de caracteres. Anexar 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 StringBuilder capacidade padrão do objeto. A capacidade do objeto dobra para 32 caracteres, a nova cadeia de caracteres é 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 anexar faz com que o comprimento do objeto StringBuilder exceda a sua capacidade, a sua capacidade existente é dobrada e a operação Append é 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 são usados se você chamar os construtores StringBuilder() e 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
capacityparâmetro quando você cria o objeto. - Atribuindo explicitamente um novo valor à StringBuilder.Capacity propriedade para expandir um objeto existente StringBuilder . (A propriedade gera uma exceção se a nova capacidade for menor que a capacidade existente ou maior que a capacidade máxima do objeto StringBuilder.)
- Chamando o método StringBuilder.EnsureCapacity com a nova capacidade. A nova capacidade não deve ser maior do que a StringBuilder capacidade máxima do objeto. No entanto, ao contrário da atribuição à propriedade Capacity, EnsureCapacity não lança 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. Não é possível 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, a 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 objeto StringBuilder provavelmente vier a crescer de forma extraordinária, geralmente excedendo vários megabytes. Nesse caso, pode haver algum benefício de desempenho ao definir a propriedade inicial Capacity para um valor significativamente alto para eliminar a necessidade de muitas realocações de memória.
- Se o seu código estiver sendo executado em um sistema com memória limitada. Nesse caso, você pode considerar definir a MaxCapacity propriedade como menor do que Int32.MaxValue se seu código estiver manipulando 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, listados na tabela a seguir. Três dos construtores instanciam um StringBuilder objeto cujo valor é uma cadeia de caracteres vazia, mas definem seus Capacity e MaxCapacity valores de forma diferente. Os três construtores restantes definem um StringBuilder objeto que tem um valor de cadeia de caracteres específico e capacidade. 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: {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 os 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 de retorno, 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 realizar uma série de chamadas de método numa instrução única. 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 métodos da StringBuilder 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 StringBuilder propriedade padrão da classe. Isso permite que você defina ou recupere caracteres individuais usando apenas seu índice, sem fazer referência explícita à Chars[Int32] propriedade. Os caracteres em um StringBuilder objeto começam no índice 0 (zero) e continuam no índice Length - 1.
O exemplo a seguir ilustra a Chars[Int32] 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 diminui o número em 1 (ou altera 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 Chars[Int32] propriedade pode ser extremamente lento nas seguintes condições:
- A StringBuilder instância é grande (por exemplo, consiste em várias dezenas de milhares de caracteres).
- O StringBuilder é "grosso". 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 é severamente afetado porque cada acesso a caracteres percorre toda a lista vinculada de partes para encontrar o buffer correto para indexação.
Nota
Mesmo para um objeto grande "chunky" StringBuilder, usar a propriedade Chars[Int32] para acesso baseado em índice a um ou a um pequeno número de caracteres tem um impacto insignificante no desempenho; normalmente é uma operação O(n). O impacto significativo no desempenho ocorre ao iterar os caracteres no StringBuilder objeto, que é uma operação O(n^2).
Se você encontrar problemas de desempenho ao usar a indexação baseada em caracteres com StringBuilder objetos, poderá usar qualquer uma das seguintes soluções alternativas:
Converta a StringBuilder instância em um String chamando o ToString método e, em seguida, acesse os caracteres na cadeia de caracteres.
Copie o conteúdo do objeto existente StringBuilder para um novo objeto pré-dimensionado StringBuilder . O desempenho melhora porque o novo StringBuilder objeto não é volumoso. 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)Defina a StringBuilder capacidade inicial do objeto para um valor que seja aproximadamente igual ao seu tamanho máximo esperado chamando o StringBuilder(Int32) construtor. Observe que isso aloca todo o bloco de memória, mesmo que raramente StringBuilder 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 substring, 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 substring, 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 métodos Append, AppendLine, AppendFormat e Insert para expandir o texto de um objeto StringBuilder.
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 algum texto de um objeto StringBuilder, exibe os valores resultantes das propriedades de capacidade, capacidade máxima e comprimento e, em seguida, chama o método Clear para remover todos os caracteres do objeto 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: {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 no objeto inteiro StringBuilder 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 ao String.Contains, String.IndexOf, e métodos fornecidos pela String.StartsWith classe, que permitem que você pesquise o objeto para um caractere String específico ou uma substring. Determinar a presença ou a posição inicial do caractere de uma substring 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 | Prós | Contras |
|---|---|---|
| Verifique cadeias de caracteres antes de as adicionar ao objeto StringBuilder. | Útil para determinar se existe uma substring. | Não pode ser usado quando a posição do índice de uma substring é importante. |
| Chame ToString e pesquise o objeto retornado String . | Fácil de usar se você atribuir todo o texto a um StringBuilder objeto e, em seguida, 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. Lembre-se de trabalhar a partir do final do texto do objeto StringBuilder se estiver a efetuar alterações. |
| Use a Chars[Int32] propriedade para pesquisar sequencialmente um intervalo de caracteres. | Útil se estiveres preocupado com caracteres individuais ou uma pequena subcadeia de caracteres. | Complicado se o número de caracteres a pesquisar for grande ou se a lógica de pesquisa for complexa. Resulta num desempenho muito fraco para objetos que aumentaram significativamente 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 uma substring específica existe (ou seja, se você não estiver interessado na posição da substring), você poderá pesquisar strings antes de armazená-las no StringBuilder objeto. O exemplo a seguir fornece uma implementação possível. Define uma
StringBuilderFinderclasse cujo construtor recebe uma referência a um StringBuilder objeto e a substring para localizar na cadeia. Neste 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.9Copen 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.9CImports 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.9CChame 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 procurar padrões. Como os objetos StringBuilder e String utilizam a codificação UTF-16 para armazenar caracteres, as posições dos índices dos caracteres, substrings e mapeamentos 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 o texto é encontrado no String objeto.
Nota
Se você adotar essa abordagem, deverá trabalhar desde o final do objeto até seu início para não precisar converter repetidamente o StringBuilder objeto em uma cadeia de StringBuilder caracteres.
O exemplo a seguir ilustra essa abordagem. Ele armazena quatro ocorrências de cada letra do alfabeto inglês em um StringBuilder objeto. Em seguida, 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. Finalmente, ele adiciona um sublinhado antes de cada sequência de quatro caracteres, exceto para 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_Zzzzopen 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_ZzzzImports 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_ZzzzUse a StringBuilder.Chars[] propriedade para pesquisar sequencialmente um intervalo de caracteres em um StringBuilder objeto. Esta abordagem pode não ser prática se o número de caracteres a pesquisar for grande ou se a lógica de pesquisa for particularmente complexa. Para obter as implicações de desempenho do acesso baseado no índice caractere por caractere para objetos muito largos e segmentados StringBuilder, consulte a documentação da propriedade StringBuilder.Chars[].
O exemplo a seguir é idêntico em funcionalidade ao exemplo anterior, mas difere na implementação. Ele usa a Chars[Int32] propriedade para detetar quando um valor de caractere foi alterado, insere um sublinhado nessa posição e converte o primeiro caractere da 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_Zzzzopen 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_ZzzzImports 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_ZzzzArmazene StringBuilder todo o texto não modificado no objeto, chame o StringBuilder.ToString método para converter o StringBuilder objeto em um String objeto e execute as modificações no String 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 negar 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 efetuar a substituição para 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_Zzzzopen 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_ZzzzImports 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 StringBuilder objeto em um String objeto antes de poder passar a cadeia de caracteres representada pelo StringBuilder objeto para um método que tenha um String parâmetro 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.