다음을 통해 공유


System.Text.StringBuilder 클래스

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

클래스는 StringBuilder 값이 변경 가능한 문자 시퀀스인 문자열과 유사한 개체를 나타냅니다.

StringBuilder 및 문자열 형식

String 둘 다 문자 시퀀스를 나타내지만 StringBuilder 다르게 구현됩니다. String 은 변경할 수 없는 형식입니다. 즉, 개체를 수정 String 하는 것처럼 보이는 각 작업은 실제로 새 문자열을 만듭니다.

예를 들어 다음 C# 예제에서 메서드를 호출 String.Concat 하면 이름이 지정된 value문자열 변수의 값이 변경됩니다. 실제로 메서드는 Concat 메서드에 value 전달된 개체와 다른 값과 주소를 value 가진 개체를 반환합니다. 예제는 컴파일러 옵션을 사용하여 /unsafe 컴파일해야 합니다.

using System;

public class Example7
{
    public unsafe static void Main()
    {
        string value = "This is the first sentence" + ".";
        fixed (char* start = value)
        {
            value = String.Concat(value, "This is the second sentence. ");
            fixed (char* current = value)
            {
                Console.WriteLine(start == current);
            }
        }
    }
}
// The example displays the following output:
//      False
    let mutable value = "This is the first sentence" + "."
    use start = fixed value
    value <- System.String.Concat(value, "This is the second sentence. ")
    use current = fixed value
    printfn $"{start = current}"
// The example displays the following output:
//      False

광범위한 문자열 조작(예: 루프에서 문자열을 여러 번 수정하는 앱)을 수행하는 루틴의 경우 문자열을 반복적으로 수정하면 상당한 성능 저하가 발생할 수 있습니다. 대안은 변경 가능한 문자열 클래스인 사용을 StringBuilder위한 것입니다. 변경 가능성은 클래스의 인스턴스가 만들어지면 문자를 추가, 제거, 바꾸기 또는 삽입하여 수정할 수 있음을 의미합니다.

Important

클래스는 StringBuilder 일반적으로 클래스보다 String 더 나은 성능을 제공하지만 문자열을 조작할 때마다 자동으로 String StringBuilder 대체해서는 안 됩니다. 성능은 문자열의 크기, 새 문자열에 할당할 메모리 양, 코드가 실행되는 시스템 및 작업 유형에 따라 달라집니다. 실제로 상당한 성능 향상을 제공하는지 여부를 StringBuilder 확인하기 위해 코드를 테스트할 준비가 되어 있어야 합니다.

다음 조건에서 클래스를 String 사용하는 것이 좋습니다.

  • 코드에서 문자열에 적용할 변경 횟수가 작은 경우 이러한 경우 StringBuilder 성능이 미미하거나 성능이 향상 String되지 않을 수 있습니다.
  • 고정된 수의 연결 작업을 수행하는 경우, 특히 문자열 리터럴을 사용합니다. 이 경우 컴파일러는 연결 작업을 단일 작업으로 결합할 수 있습니다.
  • 문자열을 빌드하는 동안 광범위한 검색 작업을 수행해야 하는 경우 클래스에 StringBuilder 와 같은 IndexOf 검색 메서드가 StartsWith없습니다. 개체를 StringBuilder 이러한 작업에 대한 개체로 String 변환해야 하며, 이렇게 하면 사용 StringBuilder으로 인한 성능 이점이 무효화됩니다. 자세한 내용은 StringBuilder 개체 섹션의 텍스트 검색을 참조하세요.

다음 조건에서 클래스를 StringBuilder 사용하는 것이 좋습니다.

  • 코드가 디자인 타임에 알 수 없는 개수의 문자열을 변경할 것으로 예상하는 경우(예: 루프를 사용하여 사용자 입력이 포함된 난수의 문자열을 연결한 경우)
  • 코드에서 문자열을 상당히 많이 변경할 것으로 예상되는 경우

StringBuilder 작동 방식

이 속성은 StringBuilder.Length 개체에 StringBuilder 현재 포함된 문자 수를 나타냅니다. 개체에 StringBuilder 문자를 추가하면 개체가 포함할 수 있는 문자 수를 정의하는 속성의 StringBuilder.Capacity 크기와 같을 때까지 길이가 증가합니다. 추가된 문자 수가 개체의 StringBuilder 길이가 현재 용량을 초과하면 새 메모리가 할당되고, 속성 값 Capacity 이 두 배로 늘어나고, 새 문자가 개체에 StringBuilder 추가되고, 해당 Length 속성이 조정됩니다. 개체에 StringBuilder 대한 추가 메모리는 속성에 정의된 StringBuilder.MaxCapacity 값에 도달할 때까지 동적으로 할당됩니다. 최대 용량에 도달하면 개체에 더 이상 메모리를 StringBuilder 할당할 수 없으며 문자를 추가하거나 최대 용량을 초과하여 확장하려고 하면 예외가 ArgumentOutOfRangeException OutOfMemoryException throw됩니다.

다음 예제에서는 개체가 StringBuilder 새 메모리를 할당하고 개체에 할당된 문자열이 확장됨에 따라 동적으로 용량을 늘리는 방법을 보여 줍니다. 이 코드는 기본(매개 변수 없는) 생성자를 호출하여 개체를 만듭니다 StringBuilder . 이 개체의 기본 용량은 16자이며 최대 용량은 20억 자 이상입니다. "이것은 문장입니다." 문자열을 추가하면 문자열 길이(19자)가 개체의 기본 용량을 초과하기 때문에 새 메모리 할당이 StringBuilder 발생합니다. 개체의 용량이 32자로 두 배로 늘어나고, 새 문자열이 추가되고, 개체의 길이가 이제 19자입니다. 그런 다음 코드는 개체의 값에 "이것은 추가 문장입니다."라는 문자열을 StringBuilder 11번 추가합니다. 추가 작업으로 인해 개체의 StringBuilder 길이가 용량을 초과할 때마다 기존 용량이 두 배로 늘어나고 Append 작업이 성공합니다.

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

메모리 할당

개체의 StringBuilder 기본 용량은 16자이며 기본 최대 용량은 Int32.MaxValue입니다. 이러한 기본값은 생성 StringBuilder(String) 자를 호출하는 StringBuilder() 경우에 사용됩니다.

다음과 같은 방법으로 개체의 초기 용량을 StringBuilder 명시적으로 정의할 수 있습니다.

  • 개체를 StringBuilder 만들 때 매개 변수를 capacity 포함하는 생성자를 호출합니다.
  • 속성에 새 값을 명시적으로 할당하여 StringBuilder.Capacity 기존 StringBuilder 개체를 확장합니다. (새 용량이 기존 용량보다 작거나 개체의 최대 용량보다 큰 경우 속성이 StringBuilder 예외를 throw합니다.)
  • 새 용량으로 StringBuilder.EnsureCapacity 메서드를 호출합니다. 새 용량은 개체의 최대 용량보다 StringBuilder 크지 않아야 합니다. 그러나 속성 EnsureCapacityCapacity 대한 할당과 달리 원하는 새 용량이 기존 용량보다 작으면 예외를 throw하지 않습니다. 이 경우 메서드 호출은 영향을 주지 않습니다.

생성자 호출에서 개체에 StringBuilder 할당된 문자열의 길이가 기본 용량 또는 지정된 용량 Capacity 을 초과하는 경우 속성은 매개 변수로 지정된 문자열의 길이로 value 설정됩니다.

생성자를 호출하여 개체의 최대 용량을 StringBuilder 명시적으로 정의할 StringBuilder(Int32, Int32) 수 있습니다. 읽기 전용이므로 속성에 새 값을 MaxCapacity 할당하여 최대 용량을 변경할 수 없습니다.

이전 섹션에서 보여 주듯이 기존 용량이 부족할 때마다 추가 메모리가 할당되고 개체의 StringBuilder 용량이 속성에 정의된 MaxCapacity 값으로 두 배가 됩니다.

일반적으로 기본 용량과 최대 용량은 대부분의 앱에 적합합니다. 다음 조건에서 이러한 값을 설정하는 것이 좋습니다.

  • 개체의 StringBuilder 최종 크기가 크게 증가할 가능성이 있는 경우 일반적으로 몇 메가바이트 초과합니다. 이 경우 너무 많은 메모리 재할당이 필요하지 않도록 초기 Capacity 속성을 상당히 높은 값으로 설정하면 성능이 약간 향상될 수 있습니다.
  • 코드가 메모리가 제한된 시스템에서 실행 중인 경우 이 경우 코드가 MaxCapacity 메모리 제한 환경에서 실행될 수 있는 큰 문자열을 처리하는 경우보다 Int32.MaxValue 작게 속성을 설정하는 것이 좋습니다.

StringBuilder 개체 인스턴스화

다음 표에 StringBuilder 나열된 6개의 오버로드된 클래스 생성자 중 하나를 호출하여 개체를 인스턴스화합니다. 생성자 중 3개는 값이 빈 문자열인 개체를 인스턴스화 StringBuilder 하지만 값 CapacityMaxCapacity 값을 다르게 설정합니다. 나머지 세 생성자는 특정 문자열 값과 용량이 있는 개체를 정의 StringBuilder 합니다. 세 생성자 중 2개는 기본 최대 용량을 Int32.MaxValue사용하는 반면, 세 번째 생성자는 최대 용량을 설정할 수 있습니다.

생성자 문자열 값 용량 최대 생산 능력
StringBuilder() String.Empty 16 Int32.MaxValue
StringBuilder(Int32) String.Empty 매개 변수에 capacity 의해 정의됨 Int32.MaxValue
StringBuilder(Int32, Int32) String.Empty 매개 변수에 capacity 의해 정의됨 매개 변수에 maxCapacity 의해 정의됨
StringBuilder(String) 매개 변수에 value 의해 정의됨 16 또는 value. Length중 더 큰 값 Int32.MaxValue
StringBuilder(String, Int32) 매개 변수에 value 의해 정의됨 매개 변수 또는 value.에 capacity 의해 정의됩니다. Length을 선택합니다. Int32.MaxValue
StringBuilder(String, Int32, Int32, Int32) value에 의해 정의됩니다. Substring(startIndex, length) 매개 변수 또는 value.에 capacity 의해 정의됩니다. Length을 선택합니다. Int32.MaxValue

다음 예제에서는 이러한 생성자 오버로드 중 세 가지를 사용하여 개체를 인스턴스화 StringBuilder 합니다.

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

StringBuilder 메서드 호출

인스턴스에서 문자열을 수정하는 대부분의 메서드는 StringBuilder 동일한 인스턴스에 대한 참조를 반환합니다. 이렇게 하면 다음 두 가지 방법으로 메서드를 호출 StringBuilder 할 수 있습니다.

  • 다음 예제와 같이 개별 메서드를 호출하고 반환 값을 무시할 수 있습니다.

    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.
    
  • 단일 문에서 일련의 메서드 호출을 수행할 수 있습니다. 연속 작업을 연결 하는 단일 문을 작성 하려는 경우에 편리할 수 있습니다. 다음 예제에서는 이전 예제의 세 가지 메서드 호출을 한 줄의 코드로 통합합니다.

    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.
    

StringBuilder 작업 수행

클래스의 메서드를 StringBuilder 사용하여 개체의 문자를 StringBuilder 반복, 추가, 삭제 또는 수정할 수 있습니다.

StringBuilder 문자 반복

속성을 사용하여 StringBuilder.Chars[] 개체의 문자 StringBuilder 에 액세스할 수 있습니다. C# Chars[] 에서는 인덱서입니다. Visual Basic에서는 클래스의 StringBuilder 기본 속성입니다. 이렇게 하면 속성을 명시적으로 참조하지 않고 인덱스만 사용하여 개별 문자를 설정하거나 검색할 Chars[] 수 있습니다. 개체의 문자는 StringBuilder 인덱스 0(0)에서 시작하여 인덱 Length 스 - 1을 계속합니다.

다음 예제에서는 속성을 보여 줍니다 Chars[] . 개체에 10개의 난수를 추가한 StringBuilder 다음 각 문자를 반복합니다. 문자의 유니코드 범주인 UnicodeCategory.DecimalDigitNumber경우 숫자를 1로 줄이거나 값이 0인 경우 숫자를 9로 변경합니다. 이 예제에서는 개별 문자의 StringBuilder 값이 변경되기 전과 후에 개체의 내용을 표시합니다.

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

Chars[] 속성에서 문자 기반 인덱싱을 사용하면 다음과 같은 조건 하에서 성능이 매우 느려질 수 있습니다.

각 문자 액세스가 인덱싱할 올바른 버퍼를 찾기 위해 연결된 전체 청크 목록을 확인하기 때문에 성능이 심각하게 저하됩니다.

참고 항목

큰 "청키" StringBuilder 개체의 경우에도 하나 또는 적은 수의 문자에 대한 인덱스 기반 액세스를 위해 속성을 사용하면 Chars[] 성능에 미치는 영향이 미미합니다. 일반적으로 O(n) 작업입니다. StringBuilder 개체에서 문자를 반복할 때 성능에 상당한 영향이 발생합니다. O(n^2)개 작업에 영향을 줍니다.

StringBuilder 개체에서 문자 기반 인덱싱을 사용할 때 성능 문제가 발생하는 경우 다음 방법 중 하나를 사용할 수 있습니다.

  • ToString 메서드를 호출하여 StringBuilder 인스턴스를 String으로 변환한 다음, 문자열의 문자에 액세스합니다.

  • 기존 StringBuilder 개체의 콘텐츠를 크기가 미리 지정된 새로운 StringBuilder 개체로 복사합니다. 새로운 StringBuilder 개체가 청크가 아니기 때문에 성능이 향상됩니다. 예시:

    // 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)
    
  • StringBuilder(Int32) 생성자를 호출하여 StringBuilder 개체의 초기 용량을 예상된 최대 크기와 대략 동일한 값으로 설정합니다. StringBuilder가 거의 최대 용량에 도달하더라도 메모리의 전체 블록을 할당합니다.

StringBuilder 개체에 텍스트 추가

클래스에는 StringBuilder 개체의 내용을 확장하기 위한 다음 메서드가 StringBuilder 포함됩니다.

  • 이 메서드는 Append 문자열, 부분 문자열, 문자 배열, 문자 배열의 일부, 여러 번 반복되는 단일 문자 또는 기본 데이터 형식의 문자열 표현을 개체에 StringBuilder 추가합니다.

  • 이 메서드는 AppendLine 줄 종결자 또는 문자열과 줄 종결자를 개체에 StringBuilder 추가합니다.

  • 메서드는 AppendFormat 개체에 복합 형식 문자열StringBuilder 추가합니다. 결과 문자열에 포함된 개체의 문자열 표현은 현재 시스템 문화권 또는 지정된 문화권의 서식 규칙을 반영할 수 있습니다.

  • 메서드는 Insert 문자열, 부분 문자열, 문자열의 여러 반복, 문자 배열, 문자 배열의 일부 또는 개체의 지정된 위치에 기본 데이터 형식의 문자열 표현을 StringBuilder 삽입합니다. 위치는 0부터 시작하는 인덱스로 정의됩니다.

다음 예제에서는 , AppendLineInsert AppendFormat메서드를 사용하여 Append개체의 StringBuilder 텍스트를 확장합니다.

using System;
using System.Text;

public class Example6
{
    public static void Main()
    {
        // Create a StringBuilder object with no text.
        StringBuilder sb = new StringBuilder();
        // Append some text.
        sb.Append('*', 10).Append(" Adding Text to a StringBuilder Object ").Append('*', 10);
        sb.AppendLine("\n");
        sb.AppendLine("Some code points and their corresponding characters:");
        // Append some formatted text.
        for (int ctr = 50; ctr <= 60; ctr++)
        {
            sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr));
            sb.AppendLine();
        }
        // Find the end of the introduction to the column.
        int pos = sb.ToString().IndexOf("characters:") + 11 +
                  Environment.NewLine.Length;
        // Insert a column header.
        sb.Insert(pos, String.Format("{2}{0,12:X4} {1,12}{2}", "Code Unit",
                                     "Character", "\n"));

        // Convert the StringBuilder to a string and display it.      
        Console.WriteLine(sb.ToString());
    }
}
// The example displays the following output:
//    ********** Adding Text to a StringBuilder Object **********
//    
//    Some code points and their corresponding characters:
//    
//       Code Unit    Character
//            0032            2
//            0033            3
//            0034            4
//            0035            5
//            0036            6
//            0037            7
//            0038            8
//            0039            9
//            003A            :
//            003B            ;
//            003C            <
open System
open System.Text

// Create a StringBuilder object with no text.
let sb = StringBuilder()
// Append some text.
sb
    .Append('*', 10)
    .Append(" Adding Text to a StringBuilder Object ")
    .Append('*', 10)
|> ignore

sb.AppendLine "\n" |> ignore
sb.AppendLine "Some code points and their corresponding characters:" |> ignore
// Append some formatted text.
for i = 50 to 60 do
    sb.AppendFormat("{0,12:X4} {1,12}", i, Convert.ToChar i) |> ignore
    sb.AppendLine() |> ignore

// Find the end of the introduction to the column.
let pos = (string sb).IndexOf("characters:") + 11 + Environment.NewLine.Length
// Insert a column header.
sb.Insert(pos, String.Format("{2}{0,12:X4} {1,12}{2}", "Code Unit", "Character", "\n"))
|> ignore

// Convert the StringBuilder to a string and display it.
printfn $"{sb}"


// The example displays the following output:
//    ********** Adding Text to a StringBuilder Object **********
//
//    Some code points and their corresponding characters:
//
//       Code Unit    Character
//            0032            2
//            0033            3
//            0034            4
//            0035            5
//            0036            6
//            0037            7
//            0038            8
//            0039            9
//            003A            :
//            003B            ;
//            003C            <
Imports System.Text

Module Example7
    Public Sub Main()
        ' Create a StringBuilder object with no text.
        Dim sb As New StringBuilder()
        ' Append some text.
        sb.Append("*"c, 10).Append(" Adding Text to a StringBuilder Object ").Append("*"c, 10)
        sb.AppendLine()
        sb.AppendLine()
        sb.AppendLine("Some code points and their corresponding characters:")
        ' Append some formatted text.
        For ctr = 50 To 60
            sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr))
            sb.AppendLine()
        Next
        ' Find the end of the introduction to the column.
        Dim pos As Integer = sb.ToString().IndexOf("characters:") + 11 +
                           Environment.NewLine.Length
        ' Insert a column header.
        sb.Insert(pos, String.Format("{2}{0,12:X4} {1,12}{2}", "Code Unit",
                                   "Character", vbCrLf))

        ' Convert the StringBuilder to a string and display it.      
        Console.WriteLine(sb.ToString())
    End Sub
End Module
' The example displays the following output:
'       ********** Adding Text to a StringBuilder Object **********
'       
'       Some code points and their corresponding characters:
'       
'          Code Unit    Character
'               0032            2
'               0033            3
'               0034            4
'               0035            5
'               0036            6
'               0037            7
'               0038            8
'               0039            9
'               003A            :
'               003B            ;
'               003C            <

StringBuilder 개체에서 텍스트 삭제

클래스에는 StringBuilder 현재 StringBuilder 인스턴스의 크기를 줄일 수 있는 메서드가 포함되어 있습니다. 이 메서드는 Clear 모든 문자를 제거하고 속성을 0으로 설정합니다 Length . 메서드는 Remove 특정 인덱스 위치에서 시작하는 지정된 수의 문자를 삭제합니다. 또한 개체의 속성을 현재 인스턴스의 StringBuilder 길이보다 작은 값으로 설정 Length 하여 개체의 끝에서 문자를 제거할 수 있습니다.

다음은 개체에서 StringBuilder 일부 텍스트를 제거하고 결과 용량, 최대 용량 및 길이 속성 값을 표시한 다음 메서드를 호출 Clear 하여 개체에서 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

StringBuilder 개체의 텍스트 수정

메서드는 StringBuilder.Replace 전체 StringBuilder 개체 또는 특정 문자 범위에서 문자 또는 문자열의 모든 발생을 대체합니다. 다음 예제에서는 메서드를 사용하여 개체의 Replace 모든 느낌표(!)를 물음표(?) 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?

StringBuilder 개체의 텍스트 검색

클래스에는 StringBuilder 특정 문자 또는 부분 문자열에 대한 개체를 검색할 수 있도록 클래스에서 제공하는 String 메서드 및 클래스와 String.StartsWith 유사한 String.ContainsString.IndexOf메서드가 포함되지 않습니다. 부분 문자열의 현재 상태 또는 시작 문자 위치를 확인하려면 문자열 검색 메서드 또는 정규식 메서드를 사용하여 값을 검색 String 해야 합니다. 다음 표와 같이 이러한 검색을 구현하는 네 가지 방법이 있습니다.

기법 장점 단점
개체에 추가 StringBuilder 하기 전에 문자열 값을 검색합니다. 부분 문자열이 있는지 여부를 확인하는 데 유용합니다. 부분 문자열의 인덱스 위치가 중요한 경우 사용할 수 없습니다.
반환 String 된 개체를 호출 ToString 하고 검색합니다. 개체에 모든 텍스트를 할당한 다음 수정을 StringBuilder 시작하는 경우 사용하기 쉽습니다. 개체에 모든 텍스트를 추가하기 전에 수정해야 하는 경우 반복적으로 호출 ToString 하는 것이 번거롭 StringBuilder 습니다.

변경하려는 경우 개체 텍스트의 StringBuilder 끝에서 작업해야 합니다.
Chars[] 속성을 사용하여 문자 범위를 순차적으로 검색합니다. 개별 문자 또는 작은 부분 문자열에 관심이 있는 경우에 유용합니다. 검색할 문자 수가 크거나 검색 논리가 복잡한 경우 번거롭습니다.

반복된 메서드 호출을 통해 매우 크게 성장한 개체의 성능이 매우 저하됩니다.
개체를 StringBuilder 개체로 String 변환하고 개체를 String 수정합니다. 수정 횟수가 작은 경우에 유용합니다. 수정 횟수가 큰 경우 클래스의 StringBuilder 성능 이점을 부정합니다.

이러한 기술을 좀 더 자세히 살펴보겠습니다.

  • 검색의 목표가 특정 부분 문자열이 있는지 여부를 확인하는 것인 경우(즉, 부분 문자열의 위치에 관심이 없는 경우) 개체에 StringBuilder 저장하기 전에 문자열을 검색할 수 있습니다. 다음 예제에서는 하나의 가능한 구현을 제공합니다. 생성자가 개체에 StringBuilderFinder 대한 참조 StringBuilder 와 문자열에서 찾을 부분 문자열을 전달하는 클래스를 정의합니다. 이 경우 예제에서는 기록된 온도가 화씨 또는 섭씨인지 여부를 확인하고 개체의 StringBuilder 시작 부분에 적절한 입문 텍스트를 추가합니다. 난수 생성기는 섭씨 또는 화씨 도의 데이터를 포함하는 배열을 선택하는 데 사용됩니다.

    using System;
    using System.Text;
    
    public class Example9
    {
        public static void Main()
        {
            Random rnd = new Random();
            string[] tempF = { "47.6F", "51.3F", "49.5F", "62.3F" };
            string[] tempC = { "21.2C", "16.1C", "23.5C", "22.9C" };
            string[][] temps = { tempF, tempC };
    
            StringBuilder sb = new StringBuilder();
            var f = new StringBuilderFinder(sb, "F");
            var baseDate = new DateTime(2013, 5, 1);
            String[] temperatures = temps[rnd.Next(2)];
            bool isFahrenheit = false;
            foreach (var temperature in temperatures)
            {
                if (isFahrenheit)
                    sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature);
                else
                    isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}\n",
                                                     baseDate, temperature));
                baseDate = baseDate.AddDays(1);
            }
            if (isFahrenheit)
            {
                sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit");
                sb.Insert(47, "\n\n");
            }
            else
            {
                sb.Insert(0, "Average Daily Temperature in Degrees Celsius");
                sb.Insert(44, "\n\n");
            }
            Console.WriteLine(sb.ToString());
        }
    }
    
    public class StringBuilderFinder
    {
        private StringBuilder sb;
        private String text;
    
        public StringBuilderFinder(StringBuilder sb, String textToFind)
        {
            this.sb = sb;
            this.text = textToFind;
        }
    
        public bool SearchAndAppend(String stringToSearch)
        {
            sb.Append(stringToSearch);
            return stringToSearch.Contains(text);
        }
    }
    // The example displays output similar to the following:
    //    Average Daily Temperature in Degrees Celsius
    //    
    //    5/1/2013: 21.2C
    //    5/2/2013: 16.1C
    //    5/3/2013: 23.5C
    //    5/4/2013: 22.9C
    
    open System
    open System.Text
    
    type StringBuilderFinder(sb: StringBuilder, textToFind: string) =
        member _.SearchAndAppend(stringToSearch: string) =
            sb.Append stringToSearch |> ignore
            stringToSearch.Contains textToFind
    
    let tempF = [| "47.6F"; "51.3F"; "49.5F"; "62.3F" |]
    let tempC = [| "21.2C"; "16.1C"; "23.5C"; "22.9C" |]
    let temps = [| tempF; tempC |]
    
    let sb = StringBuilder()
    let f = StringBuilderFinder(sb, "F")
    let temperatures = temps[Random.Shared.Next(2)]
    let mutable baseDate = DateTime(2013, 5, 1)
    let mutable isFahrenheit = false
    
    for temperature in temperatures do
        if isFahrenheit then
            sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature) |> ignore
        else
            isFahrenheit <- $"{baseDate:d}: {temperature}\n" |> f.SearchAndAppend
    
        baseDate <- baseDate.AddDays 1
    
    if isFahrenheit then
        sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit") |> ignore
        sb.Insert(47, "\n\n") |> ignore
    
    else
        sb.Insert(0, "Average Daily Temperature in Degrees Celsius") |> ignore
        sb.Insert(44, "\n\n") |> ignore
    
    printfn $"{sb}"
    
    // The example displays output similar to the following:
    //    Average Daily Temperature in Degrees Celsius
    //
    //    5/1/2013: 21.2C
    //    5/2/2013: 16.1C
    //    5/3/2013: 23.5C
    //    5/4/2013: 22.9C
    
    Imports System.Text
    
    Module Example9
        Public Sub Main()
            Dim rnd As New Random()
            Dim tempF() As String = {"47.6F", "51.3F", "49.5F", "62.3F"}
            Dim tempC() As String = {"21.2C", "16.1C", "23.5C", "22.9C"}
            Dim temps()() As String = {tempF, tempC}
    
            Dim sb As StringBuilder = New StringBuilder()
            Dim f As New StringBuilderFinder(sb, "F")
            Dim baseDate As New DateTime(2013, 5, 1)
            Dim temperatures() As String = temps(rnd.Next(2))
            Dim isFahrenheit As Boolean = False
            For Each temperature In temperatures
                If isFahrenheit Then
                    sb.AppendFormat("{0:d}: {1}{2}", baseDate, temperature, vbCrLf)
                Else
                    isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}{2}",
                                                 baseDate, temperature, vbCrLf))
                End If
                baseDate = baseDate.AddDays(1)
            Next
            If isFahrenheit Then
                sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit")
                sb.Insert(47, vbCrLf + vbCrLf)
            Else
                sb.Insert(0, "Average Daily Temperature in Degrees Celsius")
                sb.Insert(44, vbCrLf + vbCrLf)
            End If
            Console.WriteLine(sb.ToString())
        End Sub
    End Module
    
    Public Class StringBuilderFinder
       Private sb As StringBuilder
       Private text As String
       
       Public Sub New(sb As StringBuilder, textToFind As String)
          Me.sb = sb
          text = textToFind
       End Sub
       
       Public Function SearchAndAppend(stringToSearch As String) As Boolean
          sb.Append(stringToSearch)
          Return stringToSearch.Contains(text)
       End Function
    End Class
    ' The example displays output similar to the following:
    '    Average Daily Temperature in Degrees Celsius
    '    
    '    5/1/2013: 21.2C
    '    5/2/2013: 16.1C
    '    5/3/2013: 23.5C
    '    5/4/2013: 22.9C
    
  • 메서드를 StringBuilder.ToString 호출하여 개체를 StringBuilder 개체로 String 변환합니다. 같은 String.LastIndexOf 메서드를 사용하여 문자열을 검색하거나 String.StartsWith정규식 및 클래스를 Regex 사용하여 패턴을 검색할 수 있습니다. 두 개체 모두 StringBuilder String UTF-16 인코딩을 사용하여 문자를 저장하기 때문에 문자, 부분 문자열 및 정규식 일치의 인덱스 위치는 두 개체 모두에서 동일합니다. 이렇게 하면 메서드를 사용하여 StringBuilder 개체에서 해당 텍스트를 찾을 String 때와 동일한 위치에서 변경할 수 있습니다.

    참고 항목

    이 방법을 채택하는 경우 개체를 문자열로 반복적으로 변환 StringBuilder 할 필요가 없도록 개체의 StringBuilder 끝에서 시작 부분으로 작업해야 합니다.

    다음 예제에서 이 방법을 보여 줍니다. 개체에 영어 알파벳의 각 문자의 네 개의 발생을 StringBuilder 저장합니다. 그런 다음 텍스트를 개체로 String 변환하고 정규식을 사용하여 각 4자 시퀀스의 시작 위치를 식별합니다. 마지막으로 첫 번째 시퀀스를 제외한 각 4자 시퀀스 앞에 밑줄을 추가하고 시퀀스의 첫 번째 문자를 대문자로 변환합니다.

    using System;
    using System.Text;
    using System.Text.RegularExpressions;
    
    public class Example10
    {
        public static void Main()
        {
            // Create a StringBuilder object with 4 successive occurrences 
            // of each character in the English alphabet. 
            StringBuilder sb = new StringBuilder();
            for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++)
                sb.Append(Convert.ToChar(ctr), 4);
    
            // Create a parallel string object.
            String sbString = sb.ToString();
            // Determine where each new character sequence begins.
            String pattern = @"(\w)\1+";
            MatchCollection matches = Regex.Matches(sbString, pattern);
    
            // Uppercase the first occurrence of the sequence, and separate it
            // from the previous sequence by an underscore character.
            for (int ctr = matches.Count - 1; ctr >= 0; ctr--)
            {
                Match m = matches[ctr];
                sb[m.Index] = Char.ToUpper(sb[m.Index]);
                if (m.Index > 0) sb.Insert(m.Index, "_");
            }
            // Display the resulting string.
            sbString = sb.ToString();
            int line = 0;
            do
            {
                int nChars = line * 80 + 79 <= sbString.Length ?
                                    80 : sbString.Length - line * 80;
                Console.WriteLine(sbString.Substring(line * 80, nChars));
                line++;
            } while (line * 80 < sbString.Length);
        }
    }
    // The example displays the following output:
    //    Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
    //    Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
    
    open System
    open System.Text
    open System.Text.RegularExpressions
    
    // Create a StringBuilder object with 4 successive occurrences
    // of each character in the English alphabet.
    let sb = StringBuilder()
    
    for char in 'a' .. 'z' do
        sb.Append(char, 4) |> ignore
    
    // Create a parallel string object.
    let sbString = string sb
    // Determine where each new character sequence begins.
    let pattern = @"(\w)\1+"
    let matches = Regex.Matches(sbString, pattern)
    
    // Uppercase the first occurrence of the sequence, and separate it
    // from the previous sequence by an underscore character.
    for i = matches.Count - 1 downto 0 do
        let m = matches[i]
        sb[m.Index] <- Char.ToUpper sb[m.Index]
    
        if m.Index > 0 then
            sb.Insert(m.Index, "_") |> ignore
    
    // Display the resulting string.
    let sbString2 = string sb
    
    for line = 0 to (sbString2.Length - 1) / 80 do
        let nChars =
            if line * 80 + 79 <= sbString2.Length then
                80
            else
                sbString2.Length - line * 80
    
        printfn $"{sbString2.Substring(line * 80, nChars)}"
    
    
    // The example displays the following output:
    //    Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
    //    Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
    
    Imports System.Text
    Imports System.Text.RegularExpressions
    
    Module Example10
        Public Sub Main()
            ' Create a StringBuilder object with 4 successive occurrences 
            ' of each character in the English alphabet. 
            Dim sb As New StringBuilder()
            For ctr As UShort = AscW("a") To AscW("z")
                sb.Append(ChrW(ctr), 4)
            Next
            ' Create a parallel string object.
            Dim sbString As String = sb.ToString()
            ' Determine where each new character sequence begins.
            Dim pattern As String = "(\w)\1+"
            Dim matches As MatchCollection = Regex.Matches(sbString, pattern)
    
            ' Uppercase the first occurrence of the sequence, and separate it
            ' from the previous sequence by an underscore character.
            For ctr As Integer = matches.Count - 1 To 0 Step -1
                Dim m As Match = matches(ctr)
                sb.Chars(m.Index) = Char.ToUpper(sb.Chars(m.Index))
                If m.Index > 0 Then sb.Insert(m.Index, "_")
            Next
            ' Display the resulting string.
            sbString = sb.ToString()
            Dim line As Integer = 0
            Do
                Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length,
                                        80, sbString.Length - line * 80)
                Console.WriteLine(sbString.Substring(line * 80, nChars))
                line += 1
            Loop While line * 80 < sbString.Length
        End Sub
    End Module
    ' The example displays the following output:
    '    Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_
    '    Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz
    
  • 개체의 StringBuilder.Chars[] 문자 StringBuilder 범위를 순차적으로 검색하려면 이 속성을 사용합니다. 검색할 문자 수가 크거나 검색 논리가 특히 복잡한 경우에는 이 방법이 실용적이지 않을 수 있습니다. 매우 큰 청크 StringBuilder 분할 개체에 대한 문자별 인덱스 기반 액세스의 성능에 미치는 영향은 속성에 대한 StringBuilder.Chars[] 설명서를 참조하세요.

    다음 예제는 이전 예제와 기능에서 동일하지만 구현은 다릅니다. 속성을 사용하여 Chars[] 문자 값이 변경된 시기를 감지하고, 해당 위치에 밑줄을 삽입하고, 새 시퀀스의 첫 번째 문자를 대문자로 변환합니다.

    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
    
  • 수정되지 않은 모든 텍스트를 개체에 StringBuilder 저장하고, 메서드를 StringBuilder.ToString 호출하여 개체를 개체로 String 변환 StringBuilder 하고, 개체에 대한 String 수정을 수행합니다. 몇 가지 수정 사항만 있는 경우 이 방법을 사용할 수 있습니다. 그렇지 않으면 변경할 수 없는 문자열을 사용하는 비용이 개체 사용 StringBuilder 의 성능 이점을 부정할 수 있습니다.

    다음 예제는 이전의 두 예제와 기능에서 동일하지만 구현은 다릅니다. 개체를 StringBuilder 만들고 개체로 String 변환한 다음 정규식을 사용하여 문자열에 대한 나머지 모든 수정을 수행합니다. 메서드는 Regex.Replace(String, String, MatchEvaluator) 람다 식을 사용하여 각 일치 항목에서 대체를 수행합니다.

    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
    

StringBuilder 개체를 문자열로 변환

StringBuilder 개체에 표시되는 문자열을 String 매개 변수를 가진 메서드에 전달하거나 사용자 인터페이스에 표시하려면 StringBuilder 개체를 String 개체로 변환해야 합니다. 메서드를 호출하여 이 변환을 수행합니다 StringBuilder.ToString . 예를 들어 정규식 메서드에 전달할 수 있도록 개체를 문자열로 변환 StringBuilder 하기 위해 메서드를 호출 ToString 하는 이전 예제를 참조하세요.