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 exactement entraîner une pénalité significative en matière de 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. Un StringBuilder objet gère une mémoire tampon pour prendre en charge les expansions vers la chaîne. De nouvelles données sont ajoutées à la mémoire tampon si la salle est disponible ; sinon, une nouvelle mémoire tampon plus grande est allouée, les données de la mémoire tampon d’origine sont copiées dans la nouvelle mémoire tampon et les nouvelles données sont ensuite ajoutées à la nouvelle mémoire tampon.

Important

Bien que la StringBuilder classe offre généralement de meilleures performances que la String classe, vous ne devez pas remplacer StringStringBuilder 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 ou StartsWith. 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 . Notez que 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, certaines performances peuvent tirer parti de la définition de la propriété initiale Capacity sur une valeur significativement élevée pour éliminer le besoin de trop de 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.