[C#] C #에서 변경 가능한 문자열과 변경 불가능한 문자열의 차이점은 무엇입니까?

C #에서 변경 가능한 문자열과 변경 불가능한 문자열의 차이점은 무엇입니까?



답변

가변 및 불변은 각각 “변경 가능”및 “변경 불가능”을 의미하는 영어 단어입니다. 단어의 의미는 IT 컨텍스트에서 동일합니다. 즉

  • 변경 가능한 문자열을 변경할 수 있으며
  • 변경할 수없는 문자열은 변경할 수 없습니다.

이 단어의 의미는 C # / .NET에서 다른 프로그래밍 언어 / 환경에서와 동일하지만 다른 세부 사항과 마찬가지로 유형의 이름은 (명백하게) 다를 수 있습니다.


기록을 위해 :

  • String 표준 C # / .Net 불변 문자열 유형입니다.
  • StringBuilder 표준 C # / .Net 가변 문자열 유형입니다.

C #으로 표시되는 문자열에서 “변경”에 영향을 주려면 String실제로 새 String객체를 만듭니다. 원래String 은 변경할 수 없기 때문에 변경되지 않습니다.

대부분의 경우 더 String쉬운 이유이기 때문에 사용하는 것이 좋습니다 . 예를 들어, 다른 스레드가 “내 문자열을 변경할”가능성을 고려할 필요가 없습니다. 그러나 일련의 작업을 사용하여 문자열을 구성하거나 수정해야하는 경우을 사용하는 것이 더 효율적일 수 있습니다 StringBuilder.


마지막으로, a StringBuilder는 변경할 수 없기 때문에 a가 문자열이 아니라고 주장하는 사람들을 위해 Microsoft 설명서 는 다음과 StringBuilder같이 설명합니다 .

변경 가능한 문자열 을 나타냅니다.이 클래스는 상속 될 수 없습니다.”


답변

String 불변이다

즉, 문자열을 변경할 수 없습니다. 문자열을 변경하면 (예 : 문자열을 추가하여) 실제로 새 문자열을 만듭니다.

그러나 StringBuilder 불변은 아닙니다 (대신 변할 수 있습니다)

따라서 여러 연결과 같이 문자열을 여러 번 변경해야하는 경우을 사용하십시오 StringBuilder.


답변

한 번 작성된 오브젝트는 다양한 조작을 호출하여 상태를 변경할 수 있으면 변경할 수 있으며, 그렇지 않으면 변경할 수 없습니다.

불변 문자열

C # (및 .NET)에서 문자열은 System.String 클래스로 표시됩니다. string키워드는이 클래스의 별칭입니다.

선택 System.String 클래스는 불변, 즉 한 번 그 상태를 변경할 수 없습니다 만든 .

모든 작업 그래서 당신은 같은 문자열에서 수행 Substring, Remove, Replace, 연결 사용 ‘+’연산자 등 새로운 문자열을 만들고 반환합니다.

데모는 다음 프로그램을 참조하십시오-

string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);

이것은 각각 ‘string’과 ‘mystring’을 인쇄합니다.

불변성이점 과 왜 문자열을 변경할 수 없는지 확인하려면 왜 .NET 문자열을 변경할 수 없습니까? .

가변 문자열

자주 수정하려는 문자열을 원한다면 StringBuilder클래스를 사용할 수 있습니다 . 인스턴스 에 대한 작업 StringBuilder 은 동일한 객체를 수정합니다 .

사용시기 에 대한 자세한 내용 은 StringBuilder 사용시기를StringBuilder 참조하십시오 . .


답변

stringC #에서는 모든 개체를 변경할 수 없습니다. string일단 생성 된 클래스의 객체는 자신이 생성 한 것 이외의 다른 값을 나타낼 수 없습니다. 문자열을 “변경”하는 것처럼 보이는 모든 작업은 새로운 작업을 생성합니다. 이것은 메모리에는 비효율적이지만 참조가 변경되지 않는 한 참조되는 문자열은 절대 변경되지 않기 때문에 문자열이 사용자의 형식에서 변경되지 않는다는 것을 신뢰할 수 있다는 점에서 매우 유용합니다.

반대로 변경 가능한 개체에는 변경할 수있는 데이터 필드가 있습니다. 하나 이상의 메소드가 오브젝트의 컨텐츠를 변경하거나, 작성 될 때 오브젝트의 값을 변경하는 특성을 갖습니다.

String과 가장 유사한 가변 객체가있는 StringBuffer경우 아래에서 변경되지 않도록 절대로 복사하려면 사본을 만들어야합니다. 그렇기 때문에 가변 객체가 모든 형태의 키로 사용하기에 위험한 이유Dictionary 나 자신을 변화시킬 수있는 개체를 해주는데 따른 손쉬운 셋업, 데이터 구조는 결국 프로그램을 충돌 할 데이터가 손상으로 이어지는, 알 방법이 없습니다.

그러나 내용을 변경할 수 있으므로 단일 문자 또는 이와 유사한 문자를 변경하고 싶기 때문에 완전한 사본을 만드는 것보다 훨씬 더 메모리 효율적입니다.

일반적으로 올바른 작업은 무언가를 만드는 동안 가변 객체를 사용하고 일단 완료하면 불변 객체를 사용하는 것입니다. 이것은 물론 불변의 형태를 가진 객체에 적용됩니다. 대부분의 컬렉션은 그렇지 않습니다. 컬렉션의 내부 상태를 다른 컨텍스트로 보낼 때 변경 불가능한 읽기 전용 형식의 컬렉션을 제공하는 것이 종종 유용합니다. 데이터.


답변

불변 :

객체에서 일부 작업을 수행하면 새 객체가 생성되므로 문자열의 경우와 같이 상태를 수정할 수 없습니다.

변하기 쉬운

객체에 대한 작업을 수행하면 StringBuilder의 경우와 같이 객체 자체가 수정되지 않은 새로운 객체가 수정되었습니다.


답변

.NET에서 System.String (일명 문자열)은 변경할 수없는 개체입니다. 즉, 객체를 만들 때 나중에 값을 변경할 수 없습니다. 변경할 수없는 객체 만 다시 만들 수 있습니다.

System.Text.StringBuilder는 System.String과 동일하게 변경 가능하며 값을 변경할 수 있습니다.

예를 들어 :

class Program
{
    static void Main(string[] args)
    {

        System.String str = "inital value";
        str = "\nsecond value";
        str = "\nthird value";

        StringBuilder sb = new StringBuilder();
        sb.Append("initial value");
        sb.AppendLine("second value");
        sb.AppendLine("third value");
    }
}

다음 MSIL을 생성합니다. 코드를 조사한 경우. System.String의 객체를 변경할 때마다 실제로 새로운 객체를 생성하고 있음을 알 수 있습니다. 그러나 System.Text.StringBuilder에서는 텍스트 값을 변경할 때마다 개체를 다시 만들지 않습니다.

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       62 (0x3e)
  .maxstack  2
  .locals init ([0] string str,
           [1] class [mscorlib]System.Text.StringBuilder sb)
  IL_0000:  nop
  IL_0001:  ldstr      "inital value"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "\nsecond value"
  IL_000c:  stloc.0
  IL_000d:  ldstr      "\nthird value"
  IL_0012:  stloc.0
  IL_0013:  newobj     instance void [mscorlib]System.Text.StringBuilder::.ctor()
  IL_0018:  stloc.1
  IL_0019:  ldloc.1
  IL_001a:  ldstr      "initial value"
  IL_001f:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
  IL_0024:  pop
  IL_0025:  ldloc.1
  IL_0026:  ldstr      "second value"
  IL_002b:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
  IL_0030:  pop
  IL_0031:  ldloc.1
  IL_0032:  ldstr      "third value"
  IL_0037:  callvirt   instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
  IL_003c:  pop
  IL_003d:  ret
} // end of method Program::Main


답변

.NET은이면에서 문자열 풀을 사용하므로 문자열을 변경할 수 있습니다. 그 뜻은 :

string name = "My Country";
string name2 = "My Country";

name과 name2는 모두 문자열 풀에서 동일한 메모리 위치를 참조합니다. 이제 name2를 다음과 같이 변경한다고 가정하십시오.

name2 = "My Loving Country";

문자열 “My Loving Country”에 대한 문자열 풀을 살펴보면 참조를 얻을 수 있습니다. 현명한 새 문자열 “My Loving Country”가 문자열 풀에 만들어지고 name2가 참조를 얻습니다. 그러나 이름 과 같은 다른 변수 가 여전히 사용하고 있기 때문에이 전체 프로세스 ” 내 국가 “는 변경되지 않았습니다 . 이것이 문자열이 IMMUTABLE 인 이유 입니다.

StringBuilder 는 다른 방식으로 작동하며 문자열 풀을 사용하지 않습니다. StringBuilder 인스턴스를 만들 때 :

var address  = new StringBuilder(500);

이 인스턴스에 대해 500 바이트 크기의 메모리 청크를 할당하고 모든 조작은이 메모리 위치를 수정하며이 메모리는 다른 오브젝트와 공유되지 않습니다. 이것이 StringBuilder변경 가능한 이유 입니다 . 입니다.

도움이 되길 바랍니다.