문제

나는 이것이 매우 어리석은 질문이라는 것을 두려워하지만, 나는 무언가를 놓치고있을 것이다.

왜 사용하고 싶어할까요? String.copy (String)?

문서는이 방법을 말합니다

지정된 문자열과 동일한 값으로 새 인스턴스를 생성합니다.

.NET에서 문자열이 불변이기 때문에이 방법을 사용하면 어떤 이점이 있는지 잘 모르겠습니다.

 string copy = String.Copy(otherString);

모든 실제 목적을 위해

 string copy = otherString;

즉, 진행중인 내부 부기를 제외하고는 사본이 아니라는 사실을 제외하고는 ReferenceEquals 다른 사람들에게는 관찰 가능한 차이가 없습니다. 문자열은 평등이 정체성이 아닌 가치에 근거한 불변의 계급입니다. (내 원래의 문구가 정확하지 않다는 것을 지적한 @andrew Hare 덕분 Copying and some, 그러나 인식 된 부족에 대해 걱정했다. 유용한 차이점.)

물론 통과했을 때 null 인수, 사본은 an을 던집니다 ArgumentNullException, "새 인스턴스"는 더 많은 메모리를 소비 할 수 있습니다. 후자는 혜택처럼 보이지 않으며, Null Check가 전체 카피 방법을 보증하기에 충분히 큰 보너스인지 확신 할 수 없습니다.

감사.

도움이 되었습니까?

해결책

와 함께 String.Copy 실제로 새로운 메모리를 할당하고 한 문자열에서 다른 문자열로 캐릭터를 복사하고 있습니다. 두 변수가 동일한 인스턴스 인 것과는 달리 완전히 새로운 인스턴스를 얻습니다. 메모리 위치를 직접 처리하고 문자열을 돌연변이 할 수있는 관리되지 않는 코드로 문자열을 사용하는 경우 중요 할 수 있습니다.

다른 팁

String.Copy 새로운 것을 반환합니다 String 그리고 동일한 결과를 얻지 못합니다

String copy = otherString;

이 시도:

using System;

class Program
{
    static void Main()
    {
        String test = "test";
        String test2 = test;
        String test3 = String.Copy(test);

        Console.WriteLine(Object.ReferenceEquals(test, test2));
        Console.WriteLine(Object.ReferenceEquals(test, test3));

        Console.ReadLine();
    }
}

설정할 때 test2 = test 이 참고 문헌은 동일하게 지적합니다 String. 그만큼 Copy 함수는 새로운 것을 반환합니다 String 동일한 참조 내용물 그러나 힙의 다른 물체로.


편집하다: 내가 OP의 질문에 대답하지 않았다는 사실에 화를내는 많은 사람들이 있습니다. 나는 질문 자체에서 잘못된 전제를 수정함으로써 질문에 대답했다고 생각합니다. 다음은 유사한 (과도하게 단순화되지 않은 경우) 질문과 답변이 있습니다.

의문:

나는 내 차에 차의 양쪽에 하나의 문이있는 것을 관찰했다. 나는 내가 사용하는 문에 관계없이 운전석에 앉아있을 것이라는 것이 사실이라고 생각합니다. 다른 문의 목적은 무엇입니까?

대답:

실제로 문을 사용하면 운전석에서 끝나는 것은 사실이 아닙니다. 운전자의 측면 도어를 사용하는 경우 운전석에 들어가고 승객의 측면 도어를 사용하면 승객 좌석이됩니다.

이제이 예에서 당신은 질문이 "승객의 옆문의 목적은 무엇입니까?"라는 질문이 실제로 답이 아니라고 주장 할 수 있습니다. 그러나 그 질문은 문이 어떻게 작동하는지에 대한 오해에 근거한 전적으로 전적으로 전제의 반박이 공제에 의해 다른 문의 목적에 새로운 빛을 비출 것이라는 것을 따르지 않는가?

퍼즐의 한 조각이 있습니다. 왜 그렇게하고 싶은지 설명하지는 않지만 기능적 차이를 설명하는 데 도움이됩니다.

당신이 그것을 사용하여 문자열을 고정하는 경우 fixed 키워드, 내용은 변이 가능합니다. 내 머리 꼭대기에서, 나는 당신이 이것을하고 싶은 상황을 생각할 수 없지만 가능합니다.

string original = "Hello World";
string refCopy = original;
string deepCopy = String.Copy(original);

fixed(char* pStr = original)
{
   *pStr = 'J';
}

Console.WriteLine(original);
Console.WriteLine(refCopy);
Console.WriteLine(deepCopy);

산출:

Jello World
Jello World
Hello World

.NET 4.0에 대한 BCL을 통해 빠른 검색은 string.Copy 방법은 약 6 곳에서 호출됩니다. 사용법은 대략 이러한 범주에 속합니다.

  1. 전달 된 문자열을 손상시킬 수있는 기본 기능과의 인터 로프. P/Invoke 선언에 영향을 줄 수없고 호출되는 기능을 수정할 수없는 경우 string.Copy 최선의 선택입니다.

  2. 성능의 이유로 문자열이 현장에서 수정되는 상황의 경우. 잠재적으로 긴 문자열로 몇 문자 만 소문자로 변환 해야하는 경우, 문자열을 두 번 복사하지 않고 추가 쓰레기를 만드는 유일한 방법은 그것을 돌연변이하는 것입니다.

  3. 필요하지 않은 곳에서. 일부 프로그래머는 Java 또는 C ++ 문자열에 더 익숙 할 수 있으며 C#에 문자열을 복사하는 것이 거의 유용하지 않다는 것을 알지 못할 수 있습니다.

string a = "abc";
string b = String.Copy(a);

Monitor.Enter(a); // not the same as Monitor.Enter(b);

하지만

string c = "123";
string d = c;
Monitor.Enter(c); // the same as Monitor.Enter(d);

누군가가 돌볼 방법에 관해서는, 그것이 완전성을위한 것이라고 생각합니다.


또한

StringBuilder sb = new StringBuilder(100);
sb.Append("abc");
string a = sb.ToString();
string b = String.Copy(a);

제 생각에는 a 그러면 더 많은 램을 차지할 것입니다 b, 처럼 a 크기 100의 버퍼를 가리 킵니다 StringBuilder 만들어진. (내부를보십시오 StringBuilder.ToString() 방법)


제 생각에는 StringBuilder 사용합니다 String.Copy() .NET 프레임 워크의 일부입니다 StringBuilder내용을 변경합니다 string. 그래서 a string 항상 불변은 아닙니다.

TVANFOSSON이 말한 것 외에도 (관리되지 않은 코드에서 관리되는 문자열로 사용되는 버퍼에 액세스 할 수는 없다고 생각합니다 ... 적어도 어렵다는 것을 알고 있습니다.) 문자열이 있다면 차이가있을 수 있다고 생각합니다. 멀티 스레드 기능을 위해 잠금을 수행하기 위해 개체로 사용됩니다.

예를 들어...

using System;

public class Class1
{
    string example1 = "example";
    string example2 = example1;

    public void ExampleMethod1()
    {
        lock (example1)
        {
            Console.WriteLine("Locked example 1");
            //do stuff...
        }
    }

    public void ExampleMethod2()
    {
        lock (example2)
        {
            Console.WriteLine("Locked example 2");
            //do stuff
        }
    }
}

두 예제 방법이 병렬로 실행되면 동일한 객체를 잠그므로 다른 하나는 잠금 블록 내부에있는 동안 실행할 수 없을 것입니다.

그러나 이것으로 바꾸면 ...

using System;

public class Class1
{
    string example1 = "example";
    string example2 = string.Copy(example1);

    public void ExampleMethod1()
    {
        lock (example1)
        {
            Console.WriteLine("Locked example 1");
            //do stuff...
        }
    }

    public void ExampleMethod2()
    {
        lock (example2)
        {
            Console.WriteLine("Locked example 2");
            //do stuff
        }
    }
}

그런 다음 동일한 방법을 실행하는 다른 스레드의 실행 만 차단할 것이라고 생각합니다 (즉, examplemethod1을 실행하는 스레드는 각 완료 될 때까지 잠겨 있지만 examplemethod2를 실행하는 스레드를 방해하지는 않습니다).

이것이 확실하지 않습니다 유용한 차이, 동기화를위한 더 나은 메커니즘이 있기 때문에 (잠금 문자열이 아주 좋은 생각이라고 생각하지 않습니다).

string a = "test";
string b = a;
//Object.ReferenceEquals(a,b) is true
a += "more";
//Object.ReferenceEquals(a,b) is now false !

자동 변경 감지?

.NET에서 문자열이 어떻게 구현되는지 잘 모르겠지만 Java는 좋은 참조라고 생각합니다.

Java에서는 새 String (str)도 string.copy (str)를 수행합니다. 동일한 값으로 새 문자열을 할당하십시오.

쓸모없는 것처럼 보이지만 메모리 최적화에 매우 유용합니다.

문자열에는 구현에 오프셋과 길이가있는 char []가 포함되어 있습니다. 하위 문자열과 같은 작업을 수행하면 메모리 사본을 수행하지 않지만 동일한 char []를 공유하는 새 문자열 인스턴스를 반환합니다. 대부분의 경우,이 패턴은 많은 메모리 사본과 할당을 저장합니다. 그러나 긴 큰 문자열 내에서 작은 조각을 기판하는 경우. 원래 큰 문자열도 GC 일 수 있습니다.

String longString = // read 1MB text from a text file
String memoryLeak = largeString.substring(100,102); 
largeString=null;
// memoryLeak will be sized 1MB in the memory
String smaller = new String(largeString.substring(100,102));
// smaller will be only few bytes in the memory

숨겨진 메모리 누출/폐기물을 방지하기 위해 새 문자열 객체가 자체 문자를 할당 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top