Classe System.Text.StringBuilder
Cet article vous offre des remarques complémentaires à la documentation de référence pour cette API.
La StringBuilder classe représente un objet de type chaîne dont la valeur est une séquence mutable de caractères.
StringBuilder et type String
Bien que StringBuilder les String deux représentent des séquences de caractères, elles sont implémentées différemment. String est un type immuable. Autrement dit, chaque opération qui semble modifier un String objet crée réellement une chaîne.
Par exemple, l’appel à la String.Concat méthode dans l’exemple C# suivant apparaît pour modifier la valeur d’une variable de chaîne nommée value
. En fait, la Concat méthode retourne un value
objet qui a une valeur et une adresse différentes de l’objet value
qui a été passé à la méthode. Notez que l’exemple doit être compilé à l’aide de l’option du /unsafe
compilateur.
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
Pour les routines qui effectuent une manipulation de chaîne étendue (par exemple, les applications qui modifient une chaîne plusieurs fois dans une boucle), la modification répétée d’une chaîne peut exercer une pénalité significative sur les performances. L’alternative consiste à utiliser StringBuilder, qui est une classe de chaîne mutable. La mutabilité signifie qu’une fois qu’une instance de la classe a été créée, elle peut être modifiée en ajoutant, en supprimant, en remplaçant ou en insérant des caractères.
Important
Bien que la StringBuilder classe offre généralement de meilleures performances que la String classe, vous ne devez pas remplacer String StringBuilder automatiquement par chaque fois que vous souhaitez manipuler des chaînes. Les performances dépendent de la taille de la chaîne, de la quantité de mémoire à allouer pour la nouvelle chaîne, du système sur lequel votre code s’exécute et du type d’opération. Vous devez être prêt à tester votre code pour déterminer s’il StringBuilder offre une amélioration significative des performances.
Envisagez d’utiliser la String classe dans les conditions suivantes :
- Lorsque le nombre de modifications apportées à votre code à une chaîne est petit. Dans ces cas, StringBuilder peut offrir une amélioration négligeable ou aucune amélioration des performances sur String.
- Lorsque vous effectuez un nombre fixe d’opérations de concaténation, en particulier avec des littéraux de chaîne. Dans ce cas, le compilateur peut combiner les opérations de concaténation en une seule opération.
- Lorsque vous devez effectuer des opérations de recherche étendues pendant la génération de votre chaîne. La StringBuilder classe n’a pas de méthodes de recherche telles que
IndexOf
ouStartsWith
. Vous devrez convertir l’objet StringBuilder en une String pour ces opérations, et cela peut négation des performances de l’utilisation StringBuilder. Pour plus d’informations, consultez la section Rechercher le texte dans une section d’objet StringBuilder.
Envisagez d’utiliser la StringBuilder classe dans les conditions suivantes :
- Lorsque vous attendez que votre code apporte un nombre inconnu de modifications à une chaîne au moment du design (par exemple, lorsque vous utilisez une boucle pour concaténer un nombre aléatoire de chaînes qui contiennent une entrée utilisateur).
- Lorsque vous attendez que votre code apporte un nombre significatif de modifications à une chaîne.
Fonctionnement de StringBuilder
La StringBuilder.Length propriété indique le nombre de caractères que contient actuellement l’objet StringBuilder . Si vous ajoutez des caractères à l’objet StringBuilder , sa longueur augmente jusqu’à ce qu’elle soit égale à la taille de la StringBuilder.Capacity propriété, ce qui définit le nombre de caractères que l’objet peut contenir. Si le nombre de caractères ajoutés entraîne la longueur de l’objet StringBuilder à dépasser sa capacité actuelle, la nouvelle mémoire est allouée, la valeur de la Capacity propriété est doublée, les nouveaux caractères sont ajoutés à l’objet StringBuilder et sa Length propriété est ajustée. La mémoire supplémentaire de l’objet StringBuilder est allouée dynamiquement jusqu’à ce qu’il atteigne la valeur définie par la StringBuilder.MaxCapacity propriété. Lorsque la capacité maximale est atteinte, aucune mémoire supplémentaire ne peut être allouée pour l’objet StringBuilder et essayer d’ajouter des caractères ou de l’étendre au-delà de sa capacité maximale lève une ArgumentOutOfRangeException ou une OutOfMemoryException exception.
L’exemple suivant montre comment un StringBuilder objet alloue une nouvelle mémoire et augmente sa capacité dynamiquement à mesure que la chaîne affectée à l’objet se développe. Le code crée un StringBuilder objet en appelant son constructeur par défaut (sans paramètre). La capacité par défaut de cet objet est de 16 caractères et sa capacité maximale est supérieure à 2 milliards de caractères. L’ajout de la chaîne « Il s’agit d’une phrase » entraîne une nouvelle allocation de mémoire, car la longueur de chaîne (19 caractères) dépasse la capacité par défaut de l’objet StringBuilder . La capacité de l’objet double à 32 caractères, la nouvelle chaîne est ajoutée et la longueur de l’objet est désormais égale à 19 caractères. Le code ajoute ensuite la chaîne « Il s’agit d’une phrase supplémentaire » à la valeur de l’objet StringBuilder 11 fois. Chaque fois que l’opération d’ajout entraîne la longueur de l’objet StringBuilder à dépasser sa capacité, sa capacité existante est doublée et l’opération Append réussit.
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
Allocation de mémoire
La capacité par défaut d’un StringBuilder objet est de 16 caractères et sa capacité maximale par défaut est Int32.MaxValue. Ces valeurs par défaut sont utilisées si vous appelez les constructeurs et StringBuilder(String) les StringBuilder() constructeurs.
Vous pouvez définir explicitement la capacité initiale d’un StringBuilder objet de la manière suivante :
- En appelant l’un StringBuilder des constructeurs qui inclut un
capacity
paramètre lorsque vous créez l’objet. - En affectant explicitement une nouvelle valeur à la StringBuilder.Capacity propriété pour développer un objet existant StringBuilder . (La propriété lève une exception si la nouvelle capacité est inférieure à la capacité existante ou supérieure à la capacité maximale de l’objet StringBuilder .)
- En appelant la StringBuilder.EnsureCapacity méthode avec la nouvelle capacité. La nouvelle capacité ne doit pas être supérieure à la capacité maximale de l’objet StringBuilder . Toutefois, contrairement à une affectation à la Capacity propriété, EnsureCapacity ne lève pas d’exception si la nouvelle capacité souhaitée est inférieure à la capacité existante. Dans ce cas, l’appel de méthode n’a aucun effet.
Si la longueur de la chaîne affectée à l’objet dans l’appel StringBuilder du constructeur dépasse la capacité par défaut ou la capacité spécifiée, la Capacity propriété est définie sur la longueur de la chaîne spécifiée avec le value
paramètre.
Vous pouvez définir explicitement la capacité maximale d’un StringBuilder objet en appelant le StringBuilder(Int32, Int32) constructeur. Vous ne pouvez pas modifier la capacité maximale en affectant une nouvelle valeur à la MaxCapacity propriété, car elle est en lecture seule.
Comme le montre la section précédente, chaque fois que la capacité existante est insuffisante, la mémoire supplémentaire est allouée et la capacité d’un StringBuilder objet double jusqu’à la valeur définie par la MaxCapacity propriété.
En général, la capacité par défaut et la capacité maximale sont suffisantes pour la plupart des applications. Vous pouvez envisager de définir ces valeurs dans les conditions suivantes :
- Si la taille éventuelle de l’objet StringBuilder est susceptible de croître excessivement grande, généralement en plus de plusieurs mégaoctets. Dans ce cas, il peut y avoir des avantages en matière de performances lors de la définition de la propriété initiale Capacity sur une valeur significativement élevée pour éliminer le besoin de trop nombreuses réaffectations de mémoire.
- Si votre code s’exécute sur un système avec une mémoire limitée. Dans ce cas, vous pouvez envisager de définir la MaxCapacity propriété sur moins que Int32.MaxValue si votre code gère des chaînes volumineuses susceptibles de l’entraîner à s’exécuter dans un environnement limité en mémoire.
Instancier un objet StringBuilder
Vous instanciez un StringBuilder objet en appelant l’un de ses six constructeurs de classes surchargés, répertoriés dans le tableau suivant. Trois des constructeurs instancient un StringBuilder objet dont la valeur est une chaîne vide, mais définissent ses valeurs et MaxCapacity ses Capacity valeurs différemment. Les trois constructeurs restants définissent un StringBuilder objet qui a une valeur et une capacité de chaîne spécifiques. Deux des trois constructeurs utilisent la capacité maximale par défaut, Int32.MaxValuetandis que le troisième vous permet de définir la capacité maximale.
Constructeur | Valeur de chaîne | Capacité | Capacité maximale |
---|---|---|---|
StringBuilder() | String.Empty | 16 | Int32.MaxValue |
StringBuilder(Int32) | String.Empty | Défini par le capacity paramètre |
Int32.MaxValue |
StringBuilder(Int32, Int32) | String.Empty | Défini par le capacity paramètre |
Défini par le maxCapacity paramètre |
StringBuilder(String) | Défini par le value paramètre |
16 ou value . Length, selon la valeur supérieure |
Int32.MaxValue |
StringBuilder(String, Int32) | Défini par le value paramètre |
Défini par le capacity paramètre ou value . Length, selon ce qui est plus grand. |
Int32.MaxValue |
StringBuilder(String, Int32, Int32, Int32) | défini par value . Substring(startIndex , length ) |
Défini par le capacity paramètre ou value . Length, selon ce qui est plus grand. |
Int32.MaxValue |
L’exemple suivant utilise trois de ces surcharges de constructeur pour instancier des StringBuilder objets.
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
Appeler des méthodes StringBuilder
La plupart des méthodes qui modifient la chaîne dans une StringBuilder instance retournent une référence à cette même instance. Cela vous permet d’appeler StringBuilder des méthodes de deux façons :
Vous pouvez effectuer des appels de méthode individuels et ignorer la valeur de retour, comme l’illustre l’exemple suivant.
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.
Vous pouvez effectuer une série d’appels de méthode dans une seule instruction. Cela peut être pratique si vous souhaitez écrire une instruction unique qui chaîne les opérations successives. L’exemple suivant consolide trois appels de méthode de l’exemple précédent en une seule ligne de code.
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.
Effectuer des opérations StringBuilder
Vous pouvez utiliser les méthodes de la StringBuilder classe pour itérer, ajouter, supprimer ou modifier des caractères dans un StringBuilder objet.
Itérer des caractères StringBuilder
Vous pouvez accéder aux caractères d’un StringBuilder objet à l’aide de la StringBuilder.Chars[] propriété. En C#, Chars[] est un indexeur ; en Visual Basic, il s’agit de la propriété par défaut de la StringBuilder classe. Cela vous permet de définir ou de récupérer des caractères individuels à l’aide de leur index uniquement, sans référence explicite à la Chars[] propriété. Les caractères d’un StringBuilder objet commencent à l’index 0 (zéro) et continuent à indexer Length - 1.
L’exemple suivant illustre la Chars[] propriété. Il ajoute dix nombres aléatoires à un StringBuilder objet, puis itère chaque caractère. Si la catégorie Unicode du caractère est UnicodeCategory.DecimalDigitNumber, elle diminue le nombre de 1 (ou remplace le nombre par 9 si sa valeur est 0). L’exemple montre comment afficher le contenu de l’objet StringBuilder avant et après la modification des valeurs de caractères individuels.
using System;
using System.Globalization;
using System.Text;
public class Example3
{
public static void Main()
{
Random rnd = new Random();
StringBuilder sb = new StringBuilder();
// Generate 10 random numbers and store them in a StringBuilder.
for (int ctr = 0; ctr <= 9; ctr++)
sb.Append(rnd.Next().ToString("N5"));
Console.WriteLine("The original string:");
Console.WriteLine(sb.ToString());
// Decrease each number by one.
for (int ctr = 0; ctr < sb.Length; ctr++)
{
if (Char.GetUnicodeCategory(sb[ctr]) == UnicodeCategory.DecimalDigitNumber)
{
int number = (int)Char.GetNumericValue(sb[ctr]);
number--;
if (number < 0) number = 9;
sb[ctr] = number.ToString()[0];
}
}
Console.WriteLine("\nThe new string:");
Console.WriteLine(sb.ToString());
}
}
// The example displays the following output:
// The original string:
// 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
// 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
// .00000
//
// The new string:
// 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
// 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
// .99999
open System
open System.Globalization
open System.Text
let rnd = Random()
let sb = new StringBuilder()
// Generate 10 random numbers and store them in a StringBuilder.
for _ = 0 to 9 do
rnd.Next().ToString "N5" |> sb.Append |> ignore
printfn "The original string:"
printfn $"{sb}"
// Decrease each number by one.
for i = 0 to sb.Length - 1 do
if Char.GetUnicodeCategory(sb[i]) = UnicodeCategory.DecimalDigitNumber then
let number = Char.GetNumericValue sb.[i] |> int
let number = number - 1
let number = if number < 0 then 9 else number
sb.[i] <- number.ToString()[0]
printfn "\nThe new string:"
printfn $"{sb}"
// The example displays the following output:
// The original string:
// 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
// 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
// .00000
//
// The new string:
// 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
// 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
// .99999
Imports System.Globalization
Imports System.Text
Module Example4
Public Sub Main()
Dim rnd As New Random()
Dim sb As New StringBuilder()
' Generate 10 random numbers and store them in a StringBuilder.
For ctr As Integer = 0 To 9
sb.Append(rnd.Next().ToString("N5"))
Next
Console.WriteLine("The original string:")
Console.WriteLine(sb.ToString())
Console.WriteLine()
' Decrease each number by one.
For ctr As Integer = 0 To sb.Length - 1
If Char.GetUnicodeCategory(sb(ctr)) = UnicodeCategory.DecimalDigitNumber Then
Dim number As Integer = CType(Char.GetNumericValue(sb(ctr)), Integer)
number -= 1
If number < 0 Then number = 9
sb(ctr) = number.ToString()(0)
End If
Next
Console.WriteLine("The new string:")
Console.WriteLine(sb.ToString())
End Sub
End Module
' The example displays the following output:
' The original string:
' 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00
' 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508
' .00000
'
' The new string:
' 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99
' 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497
' .99999
L’utilisation de l’indexation basée sur des caractères avec la propriété Chars[] peut être très lente dans les conditions suivantes :
- L’instance de StringBuilder est grande (par exemple, elle est constituée de plusieurs dizaines de milliers de caractères).
- Il StringBuilder s’agit de « segments ». Autrement dit, des appels répétés à des méthodes telles que StringBuilder.Append l’ont développé automatiquement la propriété de l’objet StringBuilder.Capacity et alloué de nouveaux blocs de mémoire à celui-ci.
Les performances sont gravement affectées, car chaque accès aux caractères doit parcourir toute la liste chaînée des blocs pour trouver la mémoire tampon correcte où indexer.
Remarque
Même pour un grand objet « segmenté », StringBuilder l’utilisation de la Chars[] propriété pour l’accès basé sur l’index à un ou à un petit nombre de caractères a un impact négligeable sur les performances ; en général, il s’agit d’une opération O(n). Un impact significatif sur les performances se produit par contre lors de l’itération dans les caractères contenus dans l’objet StringBuilder, qui est une opération O(n^2).
Si vous rencontrez des problèmes de performances lors de l’utilisation de l’indexation basée sur des caractères avec des objets StringBuilder, vous pouvez utiliser une des solutions de contournement suivantes :
Convertissez l’instance de StringBuilder en String en appelant la méthode ToString, puis accédez aux caractères de la chaîne.
Copiez le contenu de l’objet StringBuilder existant dans un objet StringBuilder prédimensionné. Les performances s’améliorent, car le nouvel objet StringBuilder ne contient pas de gros blocs. Par exemple :
// 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)
Définissez la capacité initiale de l’objet StringBuilder à une valeur approximativement égale à sa taille maximale attendue en appelant le constructeur StringBuilder(Int32). Notez que ceci alloue l’intégralité du bloc de mémoire, même si StringBuilder atteint rarement sa capacité maximale.
Ajouter du texte à un objet StringBuilder
La StringBuilder classe inclut les méthodes suivantes pour développer le contenu d’un StringBuilder objet :
La Append méthode ajoute une chaîne, une sous-chaîne, un tableau de caractères, une partie d’un tableau de caractères, un caractère unique répété plusieurs fois ou la représentation sous forme de chaîne d’un type de données primitif à un StringBuilder objet.
La AppendLine méthode ajoute un terminateur de ligne ou une chaîne ainsi qu’un terminateur de ligne à un StringBuilder objet.
La AppendFormat méthode ajoute une chaîne de format composite à un StringBuilder objet. Les représentations sous forme de chaîne des objets inclus dans la chaîne de résultat peuvent refléter les conventions de mise en forme de la culture système actuelle ou une culture spécifiée.
La Insert méthode insère une chaîne, une sous-chaîne, plusieurs répétitions d’une chaîne, un tableau de caractères, une partie d’un tableau de caractères ou la représentation sous forme de chaîne d’un type de données primitif à une position spécifiée dans l’objet StringBuilder . La position est définie par un index de base zéro.
L’exemple suivant utilise les méthodes , AppendLineAppendFormatet Insert les Appendméthodes pour développer le texte d’un StringBuilder objet.
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 <
Supprimer du texte d’un objet StringBuilder
La StringBuilder classe inclut des méthodes qui peuvent réduire la taille de l’instance actuelle StringBuilder . La Clear méthode supprime tous les caractères et définit la Length propriété sur zéro. La Remove méthode supprime un nombre spécifié de caractères commençant à une position d’index particulière. En outre, vous pouvez supprimer des caractères de la fin d’un StringBuilder objet en définissant sa Length propriété sur une valeur inférieure à la longueur de l’instance actuelle.
L’exemple suivant supprime certains du texte d’un StringBuilder objet, affiche sa capacité résultante, sa capacité maximale et ses valeurs de propriété de longueur, puis appelle la Clear méthode pour supprimer tous les caractères de l’objet 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
Modifier le texte dans un objet StringBuilder
La StringBuilder.Replace méthode remplace toutes les occurrences d’un caractère ou d’une chaîne dans l’objet entier StringBuilder ou dans une plage de caractères particulière. L’exemple suivant utilise la Replace méthode pour remplacer tous les points d’exclamation ( !) par des points d’interrogation ( ?) dans l’objet 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?
Rechercher le texte dans un objet StringBuilder
La StringBuilder classe n’inclut pas de méthodes similaires aux String.IndexOfString.ContainsString.StartsWith méthodes fournies par la String classe, ce qui vous permet de rechercher un caractère particulier ou une sous-chaîne. La détermination de la présence ou de la position de caractère de départ d’une sous-chaîne nécessite que vous recherchiez une String valeur à l’aide d’une méthode de recherche de chaîne ou d’une méthode d’expression régulière. Il existe quatre façons d’implémenter ces recherches, comme le montre le tableau suivant.
Technique | Avantages | Inconvénients |
---|---|---|
Recherchez des valeurs de chaîne avant de les ajouter à l’objet StringBuilder . | Utile pour déterminer si une sous-chaîne existe. | Impossible d’utiliser la position d’index d’une sous-chaîne. |
Appelez et recherchez ToString l’objet retourné String . | Facile à utiliser si vous affectez tout le texte à un StringBuilder objet, puis commencez à le modifier. | Fastidieux à appeler ToString à plusieurs reprises si vous devez apporter des modifications avant que tout le texte soit ajouté à l’objet StringBuilder . Vous devez vous rappeler de travailler à partir de la fin du texte de l’objet StringBuilder si vous apportez des modifications. |
Utilisez la Chars[] propriété pour rechercher séquentiellement une plage de caractères. | Utile si vous êtes préoccupé par des caractères individuels ou une petite sous-chaîne. | Fastidieux si le nombre de caractères à rechercher est volumineux ou si la logique de recherche est complexe. Entraîne des performances très médiocres pour les objets qui ont augmenté très grand par le biais d’appels de méthode répétés. |
Convertissez l’objet StringBuilder en objet String et effectuez des modifications sur l’objet String . | Utile si le nombre de modifications est petit. | Annule l’avantage des performances de la StringBuilder classe si le nombre de modifications est important. |
Examinons ces techniques plus en détail.
Si l’objectif de la recherche est de déterminer si une sous-chaîne particulière existe (autrement dit, si vous n’êtes pas intéressé par la position de la sous-chaîne), vous pouvez rechercher des chaînes avant de les stocker dans l’objet StringBuilder . L’exemple suivant fournit une implémentation possible. Il définit une
StringBuilderFinder
classe dont le constructeur est passé une référence à un StringBuilder objet et à la sous-chaîne à rechercher dans la chaîne. Dans ce cas, l’exemple tente de déterminer si les températures enregistrées se trouvent dans Fahrenheit ou Celsius, et ajoute le texte d’introduction approprié au début de l’objet StringBuilder . Un générateur de nombres aléatoires est utilisé pour sélectionner un tableau qui contient des données en degrés Celsius ou degrés Fahrenheit.using System; using System.Text; public class Example9 { public static void Main() { Random rnd = new Random(); string[] tempF = { "47.6F", "51.3F", "49.5F", "62.3F" }; string[] tempC = { "21.2C", "16.1C", "23.5C", "22.9C" }; string[][] temps = { tempF, tempC }; StringBuilder sb = new StringBuilder(); var f = new StringBuilderFinder(sb, "F"); var baseDate = new DateTime(2013, 5, 1); String[] temperatures = temps[rnd.Next(2)]; bool isFahrenheit = false; foreach (var temperature in temperatures) { if (isFahrenheit) sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature); else isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}\n", baseDate, temperature)); baseDate = baseDate.AddDays(1); } if (isFahrenheit) { sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit"); sb.Insert(47, "\n\n"); } else { sb.Insert(0, "Average Daily Temperature in Degrees Celsius"); sb.Insert(44, "\n\n"); } Console.WriteLine(sb.ToString()); } } public class StringBuilderFinder { private StringBuilder sb; private String text; public StringBuilderFinder(StringBuilder sb, String textToFind) { this.sb = sb; this.text = textToFind; } public bool SearchAndAppend(String stringToSearch) { sb.Append(stringToSearch); return stringToSearch.Contains(text); } } // The example displays output similar to the following: // Average Daily Temperature in Degrees Celsius // // 5/1/2013: 21.2C // 5/2/2013: 16.1C // 5/3/2013: 23.5C // 5/4/2013: 22.9C
open System open System.Text type StringBuilderFinder(sb: StringBuilder, textToFind: string) = member _.SearchAndAppend(stringToSearch: string) = sb.Append stringToSearch |> ignore stringToSearch.Contains textToFind let tempF = [| "47.6F"; "51.3F"; "49.5F"; "62.3F" |] let tempC = [| "21.2C"; "16.1C"; "23.5C"; "22.9C" |] let temps = [| tempF; tempC |] let sb = StringBuilder() let f = StringBuilderFinder(sb, "F") let temperatures = temps[Random.Shared.Next(2)] let mutable baseDate = DateTime(2013, 5, 1) let mutable isFahrenheit = false for temperature in temperatures do if isFahrenheit then sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature) |> ignore else isFahrenheit <- $"{baseDate:d}: {temperature}\n" |> f.SearchAndAppend baseDate <- baseDate.AddDays 1 if isFahrenheit then sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit") |> ignore sb.Insert(47, "\n\n") |> ignore else sb.Insert(0, "Average Daily Temperature in Degrees Celsius") |> ignore sb.Insert(44, "\n\n") |> ignore printfn $"{sb}" // The example displays output similar to the following: // Average Daily Temperature in Degrees Celsius // // 5/1/2013: 21.2C // 5/2/2013: 16.1C // 5/3/2013: 23.5C // 5/4/2013: 22.9C
Imports System.Text Module Example9 Public Sub Main() Dim rnd As New Random() Dim tempF() As String = {"47.6F", "51.3F", "49.5F", "62.3F"} Dim tempC() As String = {"21.2C", "16.1C", "23.5C", "22.9C"} Dim temps()() As String = {tempF, tempC} Dim sb As StringBuilder = New StringBuilder() Dim f As New StringBuilderFinder(sb, "F") Dim baseDate As New DateTime(2013, 5, 1) Dim temperatures() As String = temps(rnd.Next(2)) Dim isFahrenheit As Boolean = False For Each temperature In temperatures If isFahrenheit Then sb.AppendFormat("{0:d}: {1}{2}", baseDate, temperature, vbCrLf) Else isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}{2}", baseDate, temperature, vbCrLf)) End If baseDate = baseDate.AddDays(1) Next If isFahrenheit Then sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit") sb.Insert(47, vbCrLf + vbCrLf) Else sb.Insert(0, "Average Daily Temperature in Degrees Celsius") sb.Insert(44, vbCrLf + vbCrLf) End If Console.WriteLine(sb.ToString()) End Sub End Module Public Class StringBuilderFinder Private sb As StringBuilder Private text As String Public Sub New(sb As StringBuilder, textToFind As String) Me.sb = sb text = textToFind End Sub Public Function SearchAndAppend(stringToSearch As String) As Boolean sb.Append(stringToSearch) Return stringToSearch.Contains(text) End Function End Class ' The example displays output similar to the following: ' Average Daily Temperature in Degrees Celsius ' ' 5/1/2013: 21.2C ' 5/2/2013: 16.1C ' 5/3/2013: 23.5C ' 5/4/2013: 22.9C
Appelez la StringBuilder.ToString méthode pour convertir l’objet StringBuilder en objet String . Vous pouvez effectuer une recherche dans la chaîne à l’aide de méthodes telles que String.LastIndexOf ou String.StartsWith, ou vous pouvez utiliser des expressions régulières et la Regex classe pour rechercher des modèles. Étant donné que les deux StringBuilder et String les objets utilisent l’encodage UTF-16 pour stocker des caractères, les positions d’index des caractères, les sous-chaînes et les correspondances d’expression régulière sont identiques dans les deux objets. Cela vous permet d’utiliser StringBuilder des méthodes pour apporter des modifications à la même position à laquelle ce texte est trouvé dans l’objet String .
Remarque
Si vous adoptez cette approche, vous devez travailler de la fin de l’objet StringBuilder à son début afin que vous n’ayez pas à convertir StringBuilder l’objet à plusieurs reprises en chaîne.
L'exemple suivant illustre cette approche. Il stocke quatre occurrences de chaque lettre de l’alphabet anglais dans un StringBuilder objet. Il convertit ensuite le texte en objet String et utilise une expression régulière pour identifier la position de départ de chaque séquence de quatre caractères. Enfin, il ajoute un trait de soulignement avant chaque séquence à quatre caractères, à l’exception de la première séquence, et convertit le premier caractère de la séquence en majuscules.
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
Utilisez la StringBuilder.Chars[] propriété pour rechercher séquentiellement une plage de caractères dans un StringBuilder objet. Cette approche peut ne pas être pratique si le nombre de caractères à rechercher est volumineux ou si la logique de recherche est particulièrement complexe. Pour connaître les implications en termes de performances de l’accès basé sur des index de caractères par caractère pour les objets très volumineux, segmentés StringBuilder , consultez la documentation de la StringBuilder.Chars[] propriété.
L’exemple suivant est identique dans les fonctionnalités de l’exemple précédent, mais diffère dans l’implémentation. Il utilise la Chars[] propriété pour détecter lorsqu’une valeur de caractère a changé, insère un trait de soulignement à cette position et convertit le premier caractère de la nouvelle séquence en majuscules.
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
Stockez tout le texte non modifié dans l’objet StringBuilder , appelez la StringBuilder.ToString méthode pour convertir l’objet StringBuilder en String objet et effectuez les modifications sur l’objet String . Vous pouvez utiliser cette approche si vous n’avez que quelques modifications ; sinon, le coût d’utilisation de chaînes immuables peut négation des avantages en matière de performances de l’utilisation d’un StringBuilder objet.
L’exemple suivant est identique dans les fonctionnalités aux deux exemples précédents, mais diffère dans l’implémentation. Il crée un StringBuilder objet, le convertit en objet String , puis utilise une expression régulière pour effectuer toutes les modifications restantes sur la chaîne. La Regex.Replace(String, String, MatchEvaluator) méthode utilise une expression lambda pour effectuer le remplacement sur chaque correspondance.
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
Convertir l’objet StringBuilder en chaîne
Vous devez convertir l’objet StringBuilder en objet String pour pouvoir passer la chaîne représentée par l’objet StringBuilder à une méthode qui a un paramètre String ou pour l’afficher dans l’interface utilisateur. Vous effectuez cette conversion en appelant la StringBuilder.ToString méthode. Pour obtenir une illustration, consultez l’exemple précédent, qui appelle la ToString méthode pour convertir un StringBuilder objet en chaîne afin qu’il puisse être passé à une méthode d’expression régulière.