문제

테스트 할 테스트 응용 프로그램을 작성하고 StringBuilder 복사 데이터 데이터를 다른 인스턴스로 복사하고 길이가 현재 용량 이상인 경우 ildasm.exe에서 확인하지만 동일하게 보입니다.

StringBuilder를 확인하는 방법은 데이터를 새 인스턴스로 복사하고 지정된 한계로 버퍼를 키우는 방법은 무엇입니까?

도움이 되었습니까?

해결책

StringBuilder가 어떻게 구현되는지 검사하려면 반사기를 발사하고보십시오. 구현 StringBuilder.Append(string) 다음과 같다

public StringBuilder Append(string value)
{
   if (value != null)
   {
      string stringValue = this.m_StringValue;
      IntPtr currentThread = Thread.InternalGetCurrentThread();
      if (this.m_currentThread != currentThread)
      {
         stringValue = string.GetStringForStringBuilder(stringValue, stringValue.Capacity);
      }
      int length = stringValue.Length;
      int requiredLength = length + value.Length;
      if (this.NeedsAllocation(stringValue, requiredLength))
      {
         string newString = this.GetNewString(stringValue, requiredLength);
         newString.AppendInPlace(value, length);
         this.ReplaceString(currentThread, newString);
      }
      else
      {
         stringValue.AppendInPlace(value, length);
         this.ReplaceString(currentThread, stringValue);
      }
   }
   return this;
}

섹션을보십시오 NeedsAllocation, GetNewString 당신이 찾고있는 것을 찾기 위해.

다른 팁

용량은 StringBuilder에 할당 된 인접한 메모리를 나타냅니다. 용량은> = 문자열의 길이 일 수 있습니다. 용량보다 StringBuilder에 더 많은 데이터가 추가되면 StringBuilder는 자동으로 용량을 증가시킵니다. 용량이 초과 되었기 때문에 (연속 메모리가 채워지고 더 이상 버퍼 실이 없음) 더 큰 버퍼 영역이 할당되고 원래 메모리 에서이 새로운 영역으로 데이터가 복사됩니다.

데이터를 새로운 '인스턴스'에 복사하지 않고 새로운 '메모리 위치'에 복사합니다. 인스턴스는 동일하게 유지되지만 새 메모리 위치를 가리 킵니다.

FYI 편집 : 생성 중에 지정되지 않은 경우 StringBuilder의 기본 용량은 16입니다.

StringBuilder의 메모리 위치를보고 싶다면 애플리케이션을 디버그하고 디버그> Windows> 메모리를 사용하여 메모리를 확인할 수 있습니다. STMT가 실행되면 StringBuilder에 저장된 각 바이트의 주소를 실제로 볼 수 있습니다.

프로그램을 프로그래밍 방식으로 가져와야하는 경우 이 링크 도움이 될 수 있습니다.

우리는 StringBuilder가 작동하기 때문에 실제로 테스트하는 것이 아니라 자신의 즐거움을 위해 항상 단위 테스트를 작성할 수 있습니다.

StringBuilder sb = new StringBuilder(10);
Console.WriteLine("Capacity = " + sb.Capacity + " Length = " + sb.Length 
      + " MaxCapacity = " + sb.MaxCapacity);
sb.Append("1234567890");
sb.Append("1234567890");
sb.Append("1234567890");
Console.WriteLine("Capacity = " + sb.Capacity + " Length = " + sb.Length 
      + " MaxCapacity = " + sb.MaxCapacity);
Assert.AreEqual("123456789012345678901234567890"
      , sb.ToString()); // NUnit assert.

당연히 통과하고 다음과 같은 출력이 제공됩니다.

    Capacity = 10 Length = 0 MaxCapacity = 2147483647
    Capacity = 40 Length = 30 MaxCapacity = 2147483647

StringBuilder가 필요할 때 버퍼를 증가시키는 방식은 StringBuilder의 내부 코드에 의해 처리되는 것입니다. 응용 프로그램의 IL 코드에는 표시되지 않습니다. 컴파일러는 특정 방법으로 StringBuilder가 포함하는 스트링이 얼마나 큰지 알 수 없습니다. 때때로 다를 수 있기 때문입니다.

그러나 StringBuilder 일 때 하다 버퍼를 늘리면 새로운 StringBuilder 인스턴스가 발생하지 않습니다. 그것은 새로운 인스턴스에 맞는 문자열의 내부 표현을 복사 할 수 있습니다 (나는 클래스의 내부 작업이 정확히 어떤 일이 일어나는지 정확히 알지 못합니다).

리플렉터를 사용하여 StringBuilder의 작동 방식을 거의 볼 수 있습니다.

방법을 참조하십시오

StringBuilder Append(string value)

.NET 3.5의 경우 로직은 다음과 같습니다. 버퍼 길이가 새 문자열에 충분하지 않은 경우 최대 (Oldsize * 2, QuestmentSize)와 같은 길이의 새 버퍼를 작성하십시오.

다시 말해, StringBuffer는 버퍼를 두 배로 늘리려고 시도하며 충분하지 않은 경우 버퍼 크기가 새 문자열에 맞게 충분합니다.

오래된 버퍼에 대한 참조가 제거되고 이전 버퍼는 다음 쓰레기 수집으로 재생됩니다.

 class Program
    {
        static void Main()
        {
            StringBuilder sb = new StringBuilder();
            Console.WriteLine(sb.Capacity); //16

            for (int i = 0; i < 50; i++) 
                sb.Append(i + ",");

            Console.WriteLine(sb.Capacity); //256

            sb = new StringBuilder();
            Console.WriteLine(sb.Capacity); //16
        }
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top