System.Text.StringBuilder – třída
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
StringBuilder Třída představuje objekt podobný řetězci, jehož hodnota je proměnlivá posloupnost znaků.
StringBuilder versus typ String
I když StringBuilder i String oba představují sekvence znaků, jsou implementovány odlišně. String je neměnný typ. To znamená, že každá operace, která se zdá upravit String objekt, ve skutečnosti vytvoří nový řetězec.
Například volání metody v následujícím příkladu String.Concat jazyka C# se zdá změnit hodnotu řetězcové proměnné s názvem value
. Ve skutečnosti metoda vrátí objekt, Concat který má jinou value
hodnotu a adresu od objektu value
, který byl předán metodě. Všimněte si, že příklad musí být zkompilován pomocí možnosti kompilátoru /unsafe
.
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
U rutin, které provádějí rozsáhlou manipulaci s řetězci (například aplikace, které opakovaně upravují řetězec ve smyčce), můžou opakovaně upravovat řetězec, který může výrazně dosáhnout snížení výkonu. Alternativou je použití StringBuilder, což je proměnlivá řetězcová třída. Proměnlivost znamená, že po vytvoření instance třídy ji můžete upravit přidáním, odebráním, nahrazením nebo vložením znaků.
Důležité
StringBuilder I když třída obecně nabízí lepší výkon než String třída, neměli byste ji automaticky nahradit String StringBuilder pokaždé, když chcete manipulovat s řetězci. Výkon závisí na velikosti řetězce, množství paměti, které se má přidělit novému řetězci, systému, na kterém se kód spouští, a na typu operace. Měli byste být připraveni otestovat kód, abyste zjistili, jestli StringBuilder skutečně nabízí významné zlepšení výkonu.
Zvažte použití String třídy za těchto podmínek:
- Pokud je počet změn, které váš kód provede v řetězci, malý. V těchto případech může StringBuilder nabídnout zanedbatelné nebo žádné zlepšení výkonu v průběhu String.
- Při provádění pevného počtu operací zřetězení, zejména u řetězcových literálů. V tomto případě může kompilátor zkombinovat operace zřetězení do jedné operace.
- Když při sestavování řetězce potřebujete provádět rozsáhlé operace vyhledávání. Třída StringBuilder nemá vyhledávací metody, jako
IndexOf
je neboStartsWith
. Budete muset převést StringBuilder objekt na String objekt pro tyto operace a to může negovat výhodu výkonu při použití StringBuilder. Další informace najdete v části Hledání textu v objektu StringBuilder .
Zvažte použití StringBuilder třídy za těchto podmínek:
- Pokud očekáváte, že váš kód v době návrhu provede neznámý počet změn řetězce (například když použijete smyčku ke zřetězení náhodného počtu řetězců, které obsahují uživatelský vstup).
- Pokud očekáváte, že váš kód provede významný počet změn řetězce.
Princip StringBuilder
Vlastnost StringBuilder.Length označuje počet znaků, které StringBuilder objekt aktuálně obsahuje. Pokud do objektu StringBuilder přidáte znaky, jeho délka se zvětšuje, dokud se nerovná velikosti StringBuilder.Capacity vlastnosti, která definuje počet znaků, které objekt může obsahovat. Pokud počet přidaných znaků způsobí, že délka objektu StringBuilder překročí aktuální kapacitu, přidělí se nová paměť, hodnota Capacity vlastnosti se zdvojnásobí, do objektu StringBuilder se přidají nové znaky a Length jeho vlastnost se upraví. Další paměť objektu StringBuilder je přidělena dynamicky, dokud nedosáhne hodnoty definované StringBuilder.MaxCapacity vlastností. Při dosažení maximální kapacity nelze objektu přidělit StringBuilder žádnou další paměť a pokus o přidání znaků nebo jeho rozšíření nad rámec maximální kapacity vyvolá ArgumentOutOfRangeException výjimku nebo OutOfMemoryException výjimku.
Následující příklad ukazuje, jak StringBuilder objekt přiděluje novou paměť a dynamicky zvyšuje svou kapacitu, protože řetězec přiřazený k objektu se rozbalí. Kód vytvoří objekt voláním výchozího konstruktoru StringBuilder (bez parametrů). Výchozí kapacita tohoto objektu je 16 znaků a její maximální kapacita je více než 2 miliardy znaků. Připojení řetězce "Toto je věta". Výsledkem je nové přidělení paměti, protože délka řetězce (19 znaků) překračuje výchozí kapacitu objektu StringBuilder . Kapacita objektu se zdvojnásobí na 32 znaků, přidá se nový řetězec a délka objektu se teď rovná 19 znakům. Kód pak připojí řetězec "Toto je další věta" k hodnotě objektu StringBuilder 11krát. Kdykoli operace připojení způsobí, že délka objektu StringBuilder překročí jeho kapacitu, její stávající kapacita se zdvojnásobí a Append operace bude úspěšná.
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
Přidělení paměti
Výchozí kapacita objektu StringBuilder je 16 znaků a její výchozí maximální kapacita je Int32.MaxValue. Tyto výchozí hodnoty se použijí při volání StringBuilder() konstruktorů a StringBuilder(String) konstruktorů.
Počáteční kapacitu objektu StringBuilder můžete explicitně definovat následujícími způsoby:
- Voláním libovolného konstruktoru StringBuilder , který obsahuje
capacity
parametr při vytváření objektu. - Explicitním přiřazením nové hodnoty vlastnosti StringBuilder.Capacity rozbalíte existující StringBuilder objekt. (Vlastnost vyvolá výjimku, pokud je nová kapacita menší než stávající kapacita nebo větší než StringBuilder maximální kapacita objektu.)
- Voláním StringBuilder.EnsureCapacity metody s novou kapacitou. Nová kapacita nesmí být větší než maximální kapacita objektu StringBuilder . Na rozdíl od přiřazení k Capacity vlastnosti však nevyvolá výjimku, EnsureCapacity pokud je požadovaná nová kapacita menší než stávající kapacita. V tomto případě volání metody nemá žádný vliv.
Pokud délka řetězce přiřazeného k StringBuilder objektu ve volání konstruktoru překračuje výchozí kapacitu nebo zadanou kapacitu, Capacity je vlastnost nastavena na délku řetězce zadaného parametrem value
.
Maximální kapacitu objektu StringBuilder můžete explicitně definovat voláním konstruktoru StringBuilder(Int32, Int32) . Maximální kapacitu nemůžete změnit přiřazením nové hodnoty vlastnosti, protože je určena jen pro MaxCapacity čtení.
Jak ukazuje předchozí část, kdykoli je stávající kapacita nedostatečná, přidělí se další paměť a kapacita StringBuilder objektu se zdvojnásobí až na hodnotu definovanou MaxCapacity vlastností.
Obecně platí, že výchozí kapacita a maximální kapacita jsou pro většinu aplikací adekvátní. Můžete zvážit nastavení těchto hodnot za následujících podmínek:
- Pokud je pravděpodobné, že konečná velikost objektu StringBuilder bude větší než více než několik megabajtů, obvykle větší než několik megabajtů. V takovém případě může být užitek z výkonu nastavení počáteční Capacity vlastnosti na výrazně vysokou hodnotu, aby se eliminovala potřeba příliš velkého počtu relokací paměti.
- Pokud je váš kód spuštěný v systému s omezenou pamětí. V takovém případě můžete zvážit nastavení MaxCapacity vlastnosti na menší hodnotu, než Int32.MaxValue kdyby váš kód zpracovával velké řetězce, které by mohly způsobit, že se spustí v prostředí s omezenými paměťmi.
Vytvoření instance objektu StringBuilder
Vytvoříte instanci StringBuilder objektu voláním jednoho z jeho šesti přetížených konstruktorů třídy, které jsou uvedeny v následující tabulce. Tři konstruktory vytvoří instanci objektu StringBuilder , jehož hodnota je prázdný řetězec, ale nastaví jeho Capacity a MaxCapacity hodnoty odlišně. Zbývající tři konstruktory definují StringBuilder objekt, který má konkrétní řetězcovou hodnotu a kapacitu. Dva ze tří konstruktorů používají výchozí maximální kapacitu Int32.MaxValue, zatímco třetí umožňuje nastavit maximální kapacitu.
Konstruktor | Řetězcová hodnota | Kapacita | Maximální kapacita |
---|---|---|---|
StringBuilder() | String.Empty | 16 | Int32.MaxValue |
StringBuilder(Int32) | String.Empty | Definováno parametrem capacity |
Int32.MaxValue |
StringBuilder(Int32, Int32) | String.Empty | Definováno parametrem capacity |
Definováno parametrem maxCapacity |
StringBuilder(String) | Definováno parametrem value |
16 nebo value . Lengthpodle toho, co je větší |
Int32.MaxValue |
StringBuilder(String, Int32) | Definováno parametrem value |
Definováno parametrem capacity nebo value . Lengthpodle toho, co je větší. |
Int32.MaxValue |
StringBuilder(String, Int32, Int32, Int32) | Definováno .value Substring(startIndex , length ) |
Definováno parametrem capacity nebo value . Lengthpodle toho, co je větší. |
Int32.MaxValue |
Následující příklad používá tři z těchto konstruktor přetížení k vytvoření instance StringBuilder objektů.
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
Volání metod StringBuilder
Většina metod, které upravují řetězec v StringBuilder instanci, vrací odkaz na stejnou instanci. To vám umožní volat StringBuilder metody dvěma způsoby:
Můžete provádět volání jednotlivých metod a ignorovat návratové hodnoty, jak to dělá následující příklad.
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.
Řadu volání metod můžete provést v jednom příkazu. To může být praktické, pokud chcete napsat jeden příkaz, který zřetědí následné operace. Následující příklad konsoliduje tři volání metody z předchozího příkladu do jednoho řádku kódu.
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.
Provádění operací StringBuilder
Metody StringBuilder třídy můžete použít k iteraci, přidání, odstranění nebo úpravě znaků v objektu StringBuilder .
Iterace znaků StringBuilder
K znakům v objektu StringBuilder můžete přistupovat pomocí StringBuilder.Chars[] vlastnosti. V jazyce C# Chars[] je indexer. V jazyce Visual Basic je to výchozí vlastnost StringBuilder třídy. To umožňuje nastavit nebo načíst jednotlivé znaky pouze pomocí jejich indexu, aniž byste explicitně odkazovali na Chars[] vlastnost. Znaky v objektu StringBuilder začínají indexem 0 (nula) a pokračujte indexem Length - 1.
Následující příklad znázorňuje Chars[] vlastnost. Připojí k objektu StringBuilder deset náhodných čísel a pak každý znak iteruje. Pokud je UnicodeCategory.DecimalDigitNumberkategorie Unicode znaku , sníží číslo o 1 (nebo změní číslo na 9, pokud je jeho hodnota 0). Příklad zobrazuje obsah objektu StringBuilder před i po změně hodnot jednotlivých znaků.
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
Použití indexování na základě znaků s Chars[] vlastností může být extrémně pomalé za následujících podmínek:
- Instance StringBuilder je velká (například se skládá z několika desítek tisíc znaků).
- Je StringBuilder to "chunky". To znamená, že opakovaná volání metod, jako StringBuilder.Append je například automaticky rozbalila vlastnost objektu StringBuilder.Capacity a přidělila jí nové bloky paměti.
Výkon je vážně ovlivněný, protože každý přístup ke znakům provede celý propojený seznam bloků dat a najde správnou vyrovnávací paměť pro indexování.
Poznámka:
I u velkého objektu "chunky" StringBuilder má použití Chars[] vlastnosti pro přístup na základě indexu k jednomu nebo malému počtu znaků zanedbatelný dopad na výkon. Obvykle se jedná o operaci O(n ). K významnému dopadu na výkon dochází při iterování znaků v objektuStringBuilder, což je operace O(n^2).
Pokud při použití indexování na základě znaků s StringBuilder objekty narazíte na problémy s výkonem, můžete použít některé z následujících alternativních řešení:
StringBuilder Převeďte instanci na String voláním ToString metody a pak získejte přístup ke znakům v řetězci.
Zkopírujte obsah existujícího StringBuilder objektu do nového předpřipraveného StringBuilder objektu. Výkon se zlepšuje, protože nový StringBuilder objekt není chunkvý. Příklad:
// 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)
Nastavte počáteční kapacitu objektu StringBuilder na hodnotu, která se přibližně rovná maximální očekávané velikosti voláním konstruktoru StringBuilder(Int32) . Všimněte si, že tím se přidělí celý blok paměti, i když StringBuilder zřídka dosáhne maximální kapacity.
Přidání textu do objektu StringBuilder
Třída StringBuilder obsahuje následující metody pro rozšíření obsahu objektu StringBuilder :
Metoda Append připojí řetězec, podřetězce, pole znaků, část pole znaků, jeden znak se opakuje vícekrát nebo řetězcové vyjádření primitivního datového typu k objektu StringBuilder .
Metoda AppendLine připojí ukončovací znak řádku nebo řetězec spolu s ukončovacím znakem řádku k objektu StringBuilder .
Metoda AppendFormat připojí ke objektu složený formátovací StringBuilder řetězec. Řetězcové reprezentace objektů obsažených ve výsledném řetězci mohou odrážet konvence formátování aktuální jazykové verze systému nebo zadané jazykové verze.
Metoda Insert vloží řetězec, podřetězce, více opakování řetězce, pole znaků, část pole znaků nebo řetězcové vyjádření primitivního datového typu na zadané pozici v objektu StringBuilder . Pozice je definována indexem založeným na nule.
Následující příklad používá Append, , AppendLineAppendFormata Insert metody rozbalit text objektuStringBuilder.
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 <
Odstranění textu z objektu StringBuilder
Třída StringBuilder obsahuje metody, které mohou zmenšit velikost aktuální StringBuilder instance. Metoda Clear odebere všechny znaky a nastaví vlastnost na nulu Length . Metoda Remove odstraní zadaný počet znaků začínajících na určité pozici indexu. Kromě toho můžete odebrat znaky z konce objektu StringBuilder nastavením jeho Length vlastnosti na hodnotu, která je menší než délka aktuální instance.
Následující příklad odebere část textu z objektu, zobrazí jeho výslednou kapacitu StringBuilder , maximální kapacitu a délku hodnoty vlastností a potom volá metodu Clear , která odebere všechny znaky z objektu StringBuilder .
using System;
using System.Text;
public class Example5
{
public static void Main()
{
StringBuilder sb = new StringBuilder("A StringBuilder object");
ShowSBInfo(sb);
// Remove "object" from the text.
string textToRemove = "object";
int pos = sb.ToString().IndexOf(textToRemove);
if (pos >= 0)
{
sb.Remove(pos, textToRemove.Length);
ShowSBInfo(sb);
}
// Clear the StringBuilder contents.
sb.Clear();
ShowSBInfo(sb);
}
public static void ShowSBInfo(StringBuilder sb)
{
Console.WriteLine("\nValue: {0}", sb.ToString());
foreach (var prop in sb.GetType().GetProperties())
{
if (prop.GetIndexParameters().Length == 0)
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb));
}
Console.WriteLine();
}
}
// The example displays the following output:
// Value: A StringBuilder object
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
//
// Value: A StringBuilder
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
//
// Value:
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
open System.Text
let showSBInfo (sb: StringBuilder) =
for prop in sb.GetType().GetProperties() do
if prop.GetIndexParameters().Length = 0 then
printf $"{prop.Name}: {prop.GetValue sb:N0} "
printfn ""
let sb = StringBuilder "A StringBuilder object"
showSBInfo sb
// Remove "object" from the text.
let textToRemove = "object"
let pos = (string sb).IndexOf textToRemove
if pos >= 0 then
sb.Remove(pos, textToRemove.Length) |> ignore
showSBInfo sb
// Clear the StringBuilder contents.
sb.Clear() |> ignore
showSBInfo sb
// The example displays the following output:
// Value: A StringBuilder object
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
//
// Value: A StringBuilder
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
//
// Value:
// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
Imports System.Text
Module Example6
Public Sub Main()
Dim sb As New StringBuilder("A StringBuilder object")
ShowSBInfo(sb)
' Remove "object" from the text.
Dim textToRemove As String = "object"
Dim pos As Integer = sb.ToString().IndexOf(textToRemove)
If pos >= 0 Then
sb.Remove(pos, textToRemove.Length)
ShowSBInfo(sb)
End If
' Clear the StringBuilder contents.
sb.Clear()
ShowSBInfo(sb)
End Sub
Public Sub ShowSBInfo(sb As StringBuilder)
Console.WriteLine()
Console.WriteLine("Value: {0}", sb.ToString())
For Each prop In sb.GetType().GetProperties
If prop.GetIndexParameters().Length = 0 Then
Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb))
End If
Next
Console.WriteLine()
End Sub
End Module
' The example displays the following output:
' Value: A StringBuilder object
' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22
'
' Value: A StringBuilder
' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16
'
' Value:
' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0
Úprava textu v objektu StringBuilder
Metoda StringBuilder.Replace nahrazuje všechny výskyty znaku nebo řetězce v celém StringBuilder objektu nebo v určité oblasti znaků. Následující příklad používá metodu Replace nahradit všechny vykřičníky (!) otazníky (?) v objektu StringBuilder .
using System;
using System.Text;
public class Example13
{
public static void Main()
{
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Replace('!', '?');
Console.WriteLine(MyStringBuilder);
}
}
// The example displays the following output:
// Hello World?
open System.Text
let myStringBuilder = StringBuilder "Hello World!"
myStringBuilder.Replace('!', '?') |> ignore
printfn $"{myStringBuilder}"
// The example displays the following output:
// Hello World?
Imports System.Text
Module Example
Public Sub Main()
Dim MyStringBuilder As New StringBuilder("Hello World!")
MyStringBuilder.Replace("!"c, "?"c)
Console.WriteLine(MyStringBuilder)
End Sub
End Module
' The example displays the following output:
' Hello World?
Hledání textu v objektu StringBuilder
Třída StringBuilder neobsahuje metody podobné String.Contains, String.IndexOfa String.StartsWith metody poskytované String třídou, které umožňují prohledávat objekt pro určitý znak nebo podřetězení. Určení přítomnosti nebo počáteční pozice znaku podřetězce vyžaduje, abyste hledali String hodnotu pomocí metody hledání řetězce nebo metody regulárního výrazu. Existují čtyři způsoby implementace takových hledání, jak ukazuje následující tabulka.
Postup | Výhody | Nevýhody |
---|---|---|
Než je přidáte do objektu StringBuilder , prohledejte hodnoty řetězců. | Užitečné pro určení, zda existuje podřetětěr. | Nelze použít, pokud je důležité umístění indexu podřetězení. |
Zavolejte ToString a vyhledejte vrácený String objekt. | Snadno se používá, pokud přiřadíte veškerý text k objektu StringBuilder a pak ho začnete upravovat. | Těžkopádné opakované volání ToString , pokud je nutné provést úpravy před přidání veškerého textu do objektu StringBuilder . Pokud provádíte změny, nezapomeňte pracovat na konci textu objektu StringBuilder . |
Chars[] Pomocí vlastnosti můžete postupně prohledávat rozsah znaků. | Užitečné, pokud se zabýváte jednotlivými znaky nebo malým podřetědcem. | Těžkopádný, pokud je počet znaků pro hledání velký nebo pokud je logika vyhledávání složitá. Výsledkem je velmi nízký výkon pro objekty, které se velmi zvětšily prostřednictvím opakovaných volání metod. |
StringBuilder Převeďte objekt na String objekt a proveďte změny objektuString. | Užitečné, pokud je počet úprav malý. | Neguje výhodu výkonu StringBuilder třídy, pokud je počet úprav velký. |
Pojďme se podrobněji podívat na tyto techniky.
Pokud je cílem hledání určit, jestli existuje konkrétní podřetězc (to znamená, že pokud vás nezajímá pozice podřetězce), můžete řetězce před uložením do objektu StringBuilder vyhledat. Následující příklad poskytuje jednu možnou implementaci. Definuje
StringBuilderFinder
třídu, jejíž konstruktor je předán odkaz na StringBuilder objekt a podřetězce najít v řetězci. V tomto případě se příklad pokusí určit, zda zaznamenané teploty jsou v Fahrenheitu nebo Celsia, a přidá příslušný úvodní text na začátek objektu StringBuilder . Generátor náhodných čísel se používá k výběru pole, které obsahuje data ve stupních Celsia nebo stupňů Fahrenheita.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
StringBuilder.ToString Volání metody pro převod StringBuilder objektu na String objekt. Řetězec můžete prohledávat pomocí metod, jako String.LastIndexOf je nebo String.StartsWith, nebo můžete použít regulární výrazy a Regex třídu k hledání vzorů. Vzhledem k tomu, že kódování StringBuilder String UTF-16 používá kódování UTF-16, umístění indexů znaků, podřetězců a shod regulárních výrazů jsou v obou objektech stejné. Díky tomu můžete pomocí StringBuilder metod provádět změny na stejné pozici, ve které se tento text nachází v objektu String .
Poznámka:
Pokud tento přístup přijmete, měli byste pracovat od konce objektu StringBuilder na jeho začátek, abyste nemuseli objekt opakovaně převádět StringBuilder na řetězec.
Tento postup znázorňuje následující příklad. Ukládá čtyři výskyty každého písmena anglické abecedy v objektu StringBuilder . Potom převede text na String objekt a použije regulární výraz k identifikaci počáteční pozice každé čtyřznakové sekvence. Nakonec přidá podtržítko před každou čtyřznakovou sekvenci s výjimkou první sekvence a převede první znak sekvence na velká písmena.
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
StringBuilder.Chars[] Pomocí vlastnosti můžete postupně prohledávat rozsah znaků v objektuStringBuilder. Tento přístup nemusí být praktický, pokud je počet znaků, které se mají prohledávat, velký nebo je logika hledání obzvláště složitá. Informace o výkonu přístupu založeného na indexech znaků pro velmi velké blokované StringBuilder objekty najdete v dokumentaci k StringBuilder.Chars[] vlastnosti.
Následující příklad je shodný s funkcí předchozího příkladu, ale liší se v implementaci. Pomocí Chars[] vlastnosti zjistí, kdy se změnila hodnota znaku, vloží podtržítko na této pozici a převede první znak v nové sekvenci na velká písmena.
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
Uložte veškerý neupravený text v objektu StringBuilder , zavolejte metodu StringBuilder.ToString pro převod StringBuilder objektu String na objekt a proveďte změny objektu String . Tento přístup můžete použít, pokud máte pouze několik úprav; jinak by náklady na práci s neměnnými řetězci mohly negovat výhody výkonu při použití objektu StringBuilder .
Následující příklad je shodný ve funkčnosti s předchozími dvěma příklady, ale liší se v implementaci. StringBuilder Vytvoří objekt, převede ho String na objekt a pak pomocí regulárního výrazu provede všechny zbývající úpravy řetězce. Metoda Regex.Replace(String, String, MatchEvaluator) používá výraz lambda k provedení nahrazení pro každou shodu.
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
Převod objektu StringBuilder na řetězec
Před předáním String řetězce reprezentované StringBuilder objektem do metody, která má String parametr nebo jej zobrazit v uživatelském rozhraní, musíte převést StringBuilder objekt na objekt. Tento převod provedete voláním StringBuilder.ToString metody. Obrázek najdete v předchozím příkladu, který volá metodu ToString pro převod StringBuilder objektu na řetězec, aby bylo možné jej předat metodě regulárního výrazu.