문제

나는 그것을 자주 읽는다. structs는 불변이어야 합니다. 정의상 그렇지 않나요?

당신은 고려합니까? int 불변이 되려고?

int i = 0;
i = i + 123;

괜찮은 것 같아요 - 새로운 것을 얻습니다 int 다시 할당 i.이건 어때?

i++;

좋아요, 지름길이라고 생각하면 됩니다.

i = i + 1;

는 어떻습니까? struct Point?

Point p = new Point(1, 2);
p.Offset(3, 4);

이것이 실제로 요점을 변경합니까? (1, 2)?우리는 이것을 다음의 지름길로 생각하면 안 될까요? Point.Offset() 새로운 포인트를 돌려주나요?

p = p.Offset(3, 4);

이 생각의 배경은 다음과 같습니다. ID가 없는 값 유형이 어떻게 변경 가능할까요?변경되었는지 확인하려면 적어도 두 번은 살펴봐야 합니다.그런데 신분증 없이 어떻게 이런 일을 할 수 있나요?

나는 이것에 대한 추론을 복잡하게 생각하고 싶지 않습니다. ref 매개변수와 복싱.나는 또한 그것을 알고 있다 p = p.Offset(3, 4); 불변성을 훨씬 더 잘 표현합니다. p.Offset(3, 4); 하다.그러나 질문은 남아 있습니다. 정의에 따라 값 유형이 변경 불가능하지 않습니까?

업데이트

변수나 필드의 변경 가능성과 변수 값의 변경 가능성이라는 두 가지 개념이 관련되어 있다고 생각합니다.

public class Foo
{
    private Point point;
    private readonly Point readOnlyPoint;

    public Foo()
    {
        this.point = new Point(1, 2);
        this.readOnlyPoint = new Point(1, 2);
    }

    public void Bar()
    {
        this.point = new Point(1, 2);
        this.readOnlyPoint = new Point(1, 2); // Does not compile.

        this.point.Offset(3, 4); // Is now (4, 6).
        this.readOnlyPoint.Offset(3, 4); // Is still (1, 2).
    }
}

이 예에서는 필드(변경 가능한 필드와 변경 불가능한 필드)가 있습니다.값 유형 필드에는 전체 값이 포함되므로 변경할 수 없는 필드에 저장된 값 유형도 변경할 수 없어야 합니다.나는 여전히 그 결과에 매우 놀랐습니다. 읽기 전용 필드가 수정되지 않은 채로 남아 있을 것이라고 기대하지 않았습니다.

변수(상수 제외)는 항상 변경 가능하므로 값 유형의 변경 가능성에 대한 제한이 없음을 의미합니다.


답변이 그리 간단하지 않은 것 같아서 질문을 다시 말씀드리겠습니다.

다음을 고려하면.

public struct Foo
{
    public void DoStuff(whatEverArgumentsYouLike)
    {
        // Do what ever you like to do.
    }

    // Put in everything you like - fields, constants, methods, properties ...
}

완성된 버전을 주실 수 있나요? Foo 및 사용 예 - 다음을 포함할 수 있음 ref 매개 변수 및 박싱 - 모든 항목을 다시 작성할 수 없도록

foo.DoStuff(whatEverArgumentsYouLike);

~와 함께

foo = foo.DoStuff(whatEverArgumentsYouLike);
도움이 되었습니까?

해결책

객체가 생성되면 상태가 변경되지 않으면 객체는 불변입니다.

짧은 답변 : 아니오, 가치 유형은 정의에 따라 불변이 아닙니다. 스트러크와 클래스는 모두 변이 가능하거나 불변 할 수 있습니다. 네 가지 조합이 모두 가능합니다. 구조물 또는 클래스에 공공 분야가 아닌 공공 필드, 세터가있는 공개 속성 또는 개인 필드를 설정하는 메소드가있는 경우 해당 유형의 새 인스턴스를 작성하지 않고 상태를 변경할 수 있기 때문에 변경할 수 있습니다.


긴 대답 : 우선, 불변성 문제는 분야 나 속성이있는 스트러크 또는 클래스에만 적용됩니다. 가장 기본적인 유형 (숫자, 문자열 및 Null)은 본질적으로 불변이 아니기 때문에 (필드/속성) 변경할 것이 없기 때문입니다. 5는 5입니다. 5는 5에 대한 모든 작업만으로 다른 불변의 가치 만 반환합니다.

다음과 같은 변이성 구조를 만들 수 있습니다 System.Drawing.Point. 둘 다 X 그리고 Y 구조물의 필드를 수정하는 세터가 있습니다.

Point p = new Point(0, 0);
p.X = 5;
// we modify the struct through property setter X
// still the same Point instance, but its state has changed
// it's property X is now 5

어떤 사람들은 값 유형이 참조가 아니라 가치 유형 (따라서 이름)으로 전달된다는 사실과 불변성을 혼란스럽게하는 것 같습니다.

void Main()
{
    Point p1 = new Point(0, 0);
    SetX(p1, 5);
    Console.WriteLine(p1.ToString());
}

void SetX(Point p2, int value)
{
    p2.X = value;
}

이 경우 Console.WriteLine() 쓰기 "{X=0,Y=0}". 여기 p1 때문에 수정되지 않았습니다 SetX() 수정 p2 그것은 a입니다 복사p1. 이런 일이 발생합니다 p1 a 가치 유형, 그것이 아니기 때문이 아닙니다 불변 (그렇지 않음).

~해야 한다 가치 유형은 불변 할 수 없습니까? 많은 이유 ... 참조 이 질문. 대부분의 값 유형이 모든 종류의 불일치 버그로 이어지기 때문입니다. 위의 예에서는 프로그래머가 예상했을 수 있습니다 p1 되려고 (5, 0) 전화 후 SetX(). 또는 나중에 변경할 수있는 값으로 정렬하는 것을 상상해보십시오. 정렬 된 컬렉션은 더 이상 예상대로 정렬되지 않습니다. 사전과 해시도 마찬가지입니다. 그만큼 멋진 에릭 립퍼트 (블로그) a 불변성에 대한 전체 시리즈 그리고 왜 그가 C#의 미래라고 믿는가. 그의 사례 중 하나가 있습니다 이를 통해 읽기 전용 변수를 "수정"할 수 있습니다.


업데이트 : 다음과 같은 예제입니다.

this.readOnlyPoint.Offset(3, 4); // Is still (1, 2).

립퍼트가 읽기 전용 변수 수정에 대해 그의 게시물에서 언급 한 내용입니다. Offset(3,4) 실제로 수정 된 a Point, 그러나 그것은이었다 복사readOnlyPoint, 그리고 그것은 결코 할당되지 않았으므로 잃어 버렸습니다.

그리고 저것 변이 가능한 가치 유형이 사악한 이유 : 그들은 당신을 허락합니다. 생각한다 때로는 사본을 수정하는 경우, 예상치 못한 버그로 이어질 때 무언가를 수정하고 있습니다. 만약에 Point 불변이었고 Offset() 새로운 것을 반환해야합니다 Point, 그리고 당신은 그것을 할당 할 수 없었을 것입니다. readOnlyPoint. 그리고 당신은 간다 "아, 그렇습니다. 이유가 있기 때문에 읽기 전용입니다. 왜 변경하려고 했습니까? 컴파일러가 지금 나를 멈췄습니다."


업데이트 : rephrased 요청에 대해 ... 나는 당신이 무엇을하고 있는지 알고 있다고 생각합니다. 어떤면에서, 당신은 structs를 존재로 "생각"할 수 있습니다. 내부적 불변의 구조물을 수정하는 것은 수정 된 사본으로 교체하는 것과 동일합니다. CLR이 내부적으로 메모리에서하는 일이 될 수도 있습니다. (플래시 메모리가 작동하는 방식입니다. 몇 바이트 만 편집 할 수는 없으며, 킬로바이트의 전체 블록을 메모리로 읽고 원하는 몇 가지를 수정하고 전체 블록을 다시 작성해야합니다.) ", 그것은 구현 세부 사항이며 우리 개발자에게 Structs (인터페이스 또는 API, 원한다면)의 사용자로서 ~할 수 있다 변경됩니다. 우리는 그 사실을 무시할 수 없으며 "그것들을 불변으로 생각하십시오".

의견에서 "필드 또는 변수의 값에 대한 언급이 없다"고 말합니다. 모든 구조물 변수가 다른 사본을 가지고 있다고 가정하여 하나의 사본을 수정하면 다른 사본에 영향을 미치지 않습니다. 그것은 완전히 사실이 아닙니다. 아래에 표시된 줄은 대체 할 수 없습니다 ...

interface IFoo { DoStuff(); }
struct Foo : IFoo { /* ... */ }

IFoo otherFoo = new Foo();
IFoo foo = otherFoo;
foo.DoStuff(whatEverArgumentsYouLike); // line #1
foo = foo.DoStuff(whatEverArgumentsYouLike); // line #2

라인 #1과 #2는 같은 결과가 없습니다 ... 왜? 왜냐하면 foo 그리고 otherFoo 참조 동일한 박스 인스턴스 foo. 변경된 것이 무엇이든 foo 1 행에서 1 번 반사됩니다 otherFoo. 라인 #2를 대체합니다 foo 새로운 가치가 있고 아무것도하지 않습니다 otherFoo (그것을 가정합니다 DoStuff() 새로운 것을 반환합니다 IFoo 인스턴스 및 수정되지 않습니다 foo 그 자체).

Foo foo1 = new Foo(); // creates first instance
Foo foo2 = foo1; // create a copy (2nd instance)
IFoo foo3 = foo2; // no copy here! foo2 and foo3 refer to same instance

수정 foo1 영향을 미치지 않습니다 foo2 또는 foo3. 수정 foo2 반영합니다 foo3, 그러나 그렇지는 않습니다 foo1. 수정 foo3 반영합니다 foo2 그러나 그렇지 않습니다 foo1.

혼란 스럽습니까? 불변의 가치 유형을 고수하면 그 중 하나를 수정하려는 충동을 제거합니다.


업데이트 : 첫 번째 코드 샘플에서 오타가 고정되었습니다

다른 팁

돌연변이와 가치 유형은 두 가지 별도의 것입니다.

유형을 값 유형으로 정의하면 런타임이 런타임에 대한 참조 대신 값을 복사 함을 나타냅니다. 반면에 돌연변이는 구현에 따라 다르며 각 클래스는 원하는대로 구현할 수 있습니다.

돌연변이가있는 스트러크를 쓸 수는 있지만 가치 유형을 불변으로 만드는 것이 가장 좋습니다.

예를 들어 DateTime은 작업을 수행 할 때 항상 새로운 인스턴스를 만듭니다. 포인트는 변이 가능하며 변경할 수 있습니다.

귀하의 질문에 답하기 위해 : 아니오, 정의에 의해 불변이 아니며, 변이 가능하든 아니든 경우에 따라 달라집니다. 예를 들어, 사전 키 역할을해야한다면 불변이되어야합니다.

논리를 충분히 멀리까지 가져간다면, 모두 유형은 변경할 수 없습니다.참조 유형을 수정하면 아무것도 수정하는 것이 아니라 실제로 동일한 주소에 새 개체를 쓰는 것이라고 주장할 수 있습니다.

또는 어떤 언어에서든 모든 것이 변경 가능하다고 주장할 수도 있습니다. 이전에 한 가지 용도로 사용되었던 메모리가 다른 용도로 덮어쓰여지는 경우가 있기 때문입니다.

추상화를 충분히 하고 언어 기능을 충분히 무시하면 원하는 결론을 얻을 수 있습니다.

그리고 그것은 요점을 놓치고 있습니다..NET 사양에 따르면 값 유형은 변경 가능합니다.수정할 수 있습니다.

int i = 0;
Console.WriteLine(i); // will print 0, so here, i is 0
++i;
Console.WriteLine(i); // will print 1, so here, i is 1

하지만 그건 여전히 똑같아.변수 i 한 번만 선언됩니다.이 선언 이후에 일어나는 모든 일은 수정입니다.

불변 변수가 있는 함수형 언어에서는 이는 합법적이지 않습니다.++i는 불가능합니다.변수가 선언되면 고정된 값을 갖습니다.

.NET에서는 그렇지 않습니다. 수정하는 것을 막을 수 있는 방법은 없습니다. i 선언된 후입니다.

좀 더 생각해 본 후에 더 나을 수 있는 또 다른 예가 있습니다.

struct S {
  public S(int i) { this.i = i == 43 ? 0 : i; }
  private int i;
  public void set(int i) { 
    Console.WriteLine("Hello World");
    this.i = i;
  }
}

void Foo {
  var s = new S(42); // Create an instance of S, internally storing the value 42
  s.set(43); // What happens here?
}

마지막 줄에서는 논리에 따라 실제로 새 객체를 생성하고 이전 객체를 해당 값으로 덮어쓴다고 말할 수 있습니다.하지만 그건 불가능해요!새로운 객체를 생성하려면 컴파일러는 다음을 설정해야 합니다. i 42로 가변.하지만 비공개야!이는 값 43을 명시적으로 허용하지 않는(대신 0으로 설정) 사용자 정의 생성자를 통해서만 액세스할 수 있으며, 그런 다음 다음을 통해 액세스할 수 있습니다. set 불쾌한 부작용이 있는 방법입니다.컴파일러는 방법이 없습니다 단지 원하는 값으로 새 객체를 생성합니다.유일한 방법은 s.i 43으로 설정할 수 있습니다. 수정 호출을 통해 현재 객체 set().컴파일러는 프로그램의 동작을 변경하기 때문에 그렇게 할 수 없습니다(콘솔에 인쇄됨).

따라서 모든 구조체가 불변이 되려면 컴파일러는 언어 규칙을 속이고 깨뜨려야 합니다.물론, 우리가 규칙을 어길 의지가 있다면 무엇이든 증명할 수 있습니다.모든 정수도 동일하다는 것을 증명할 수 있습니다. 또는 새 클래스를 정의하면 컴퓨터에 불이 붙을 수 있다는 것을 증명할 수 있습니다.언어 규칙을 준수하는 한 구조체는 변경 가능합니다.

나는 고려함으로써 이것에 대한 추론을 복잡하게하고 싶지 않다 ref매개 변수 및 권투. 나는 또한 그것을 알고 있습니다 p = p.Offset(3, 4); 불변성을 훨씬 더 잘 표현합니다 p.Offset(3, 4); 하다. 그러나 문제는 여전히 남아 있습니다. 정의에 따라 가치 유형이 불변이되지 않습니까?

글쎄, 당신은 실제로 현실 세계에서 운영되고 있지 않습니까? 실제로, 함수 사이에서 움직일 때 자신의 사본을 만들기위한 가치 유형의 성향은 불변성과 잘 맞지 않지만, 당신이 그것들을 불변으로 만들지 않으면 실제로 불변 할 수는 없습니다. 다른 것들처럼.

정의에 따라 가치 유형이 불변 할 수 없습니까?

아니요 System.Drawing.Point 예를 들어, 구조물, 그것은 세터와 그에 대한 getter가 있습니다. X 재산.

그러나 모든 가치 유형이 있다고 말하는 것은 사실 일 수 있습니다. ~해야 한다 불변 API로 정의하십시오.

혼란은 값 유형처럼 작동 해야하는 기준 유형이 있다면 불변으로 만드는 것이 좋습니다. 값 유형과 참조 유형의 주요 차이점 중 하나는 Ref 유형의 한 이름을 통해 변경된 변경이 다른 이름으로 표시 될 수 있다는 것입니다. 이것은 값 유형으로는 발생하지 않습니다.

public class foo
{
    public int x;
}

public struct bar
{
    public int x;
}


public class MyClass
{
    public static void Main()
    {
        foo a = new foo();
        bar b = new bar();

        a.x = 1;
        b.x = 1;

        foo a2 = a;
        bar b2 = b;

        a.x = 2;
        b.x = 2;

        Console.WriteLine( "a2.x == {0}", a2.x);
        Console.WriteLine( "b2.x == {0}", b2.x);
    }
}

생산 :

a2.x == 2
b2.x == 1

이제 가치 의미를 갖고 싶지만 실제로 가치 유형으로 만들고 싶지 않은 유형이 있다면 필요한 스토리지가 너무 많거나 무엇이든, 불변성이 일부라고 생각해야합니다. 디자인. 불변의 참조 유형을 사용하면 기존 참조로 변경되면 기존 객체를 변경하는 대신 새 객체를 변경하므로 보유한 값이 다른 이름을 통해 변경 될 수없는 값 유형의 동작을 얻습니다.

물론 System.String 클래스는 그러한 행동의 대표적인 예입니다.

작년에 나는 Structs를 불변으로 만들지 않음으로써 발생할 수있는 문제에 관한 블로그 게시물을 썼습니다.

전체 게시물은 여기에서 읽을 수 있습니다.

다음은 상황이 어떻게 끔찍하게 잘못될 수 있는지 보여주는 예입니다.

//Struct declaration:

struct MyStruct
{
  public int Value = 0;

  public void Update(int i) { Value = i; }
}

코드 샘플:

MyStruct[] list = new MyStruct[5];

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

for (int i=0;i<5;i++)
  list[i].Update(i+1);

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

이 코드의 출력은 다음과 같습니다.

0 0 0 0 0
1 2 3 4 5

이제 동일한 작업을 수행하되 배열을 일반 배열로 대체해 보겠습니다. List<>:

List<MyStruct> list = new List<MyStruct>(new MyStruct[5]); 

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

for (int i=0;i<5;i++)
  list[i].Update(i+1);

for (int i=0;i<5;i++)
  Console.Write(list[i].Value + " ");
Console.WriteLine();

출력은 다음과 같습니다

0 0 0 0 0
0 0 0 0 0

설명은 매우 간단합니다.아니요, 복싱/언박싱이 아닙니다...

배열의 요소에 액세스할 때 런타임은 배열 요소를 직접 가져오므로 Update() 메서드는 배열 항목 자체에서 작동합니다.이는 배열의 구조체 자체가 업데이트됨을 의미합니다.

두 번째 예에서는 일반 이름을 사용했습니다. List<>.특정 요소에 액세스하면 어떻게 되나요?음, 인덱서 속성이 호출되는데, 이는 메서드입니다.값 유형은 메소드에 의해 반환될 때 항상 복사되므로 정확히 다음과 같은 일이 발생합니다.목록의 인덱서 메서드는 내부 배열에서 구조체를 검색하여 호출자에게 반환합니다.이는 값 유형과 관련되므로 복사본이 만들어지고 복사본에서 Update() 메서드가 호출됩니다. 물론 목록의 원래 항목에는 영향을 미치지 않습니다.

즉, 언제 복사본이 만들어질지 확신할 수 없으므로 항상 구조체가 변경 불가능한지 확인하세요.대부분의 경우 이는 명백하지만 어떤 경우에는 정말 놀랄 수도 있습니다.

아니요, 그들은 아닙니다. 예시:

Point p = new Point (3,4);
Point p2 = p;
p.moveTo (5,7);

이 예에서 moveTo() 이다 현장 작업. 참조 뒤에 숨어있는 구조를 변경합니다 p. 당신은 그것을 보면 볼 수 있습니다 p2: 위치도 바뀌 었습니다. 불변의 구조로 moveTo() 새로운 구조를 반환해야합니다.

p = p.moveTo (5,7);

지금, Point 불변이 아니며 코드의 어느 곳에서나 참조를 만들 때 놀라움을 얻지 못할 것입니다. 보자 i:

int i = 5;
int j = i;
i = 1;

이것은 다릅니다. i 불변이 아니에요 5 이다. 두 번째 과제는 포함 된 구조에 대한 참조를 복사하지 않습니다. i 그러나 그것은 내용을 복사합니다 i. 따라서 무대 뒤에서 완전히 다른 일이 발생합니다. 메모리의 주소 사본 대신 변수의 전체 사본을 얻습니다 (참조).

객체와 동등한 것은 카피 생성자입니다.

Point p = new Point (3,4);
Point p2 = new Point (p);

여기서, 내부 구조 p 새로운 객체/구조로 복사됩니다 p2 그것에 대한 참조가 포함됩니다. 그러나 이것은 위의 정수 할당과 달리 꽤 비싼 작업이므로 대부분의 프로그래밍 언어가 구별되는 이유입니다.

컴퓨터가 더욱 강력 해지고 더 많은 메모리를 얻음에 따라,이 차이는 엄청난 양의 버그와 문제를 일으키기 때문에 사라질 것입니다. 차세대에는 불변의 물체 만있을 것입니다. 모든 작업은 거래에 의해 보호됩니다. int 완전히 날아간 대상이 될 것입니다. 쓰레기 수집과 마찬가지로, 프로그램 안정성에 큰 발전이 될 것이며, 처음 몇 년 동안 많은 슬픔을 유발하지만 신뢰할 수있는 소프트웨어를 작성할 수 있습니다. 오늘날 컴퓨터는이를 위해 충분히 빠르지 않습니다.

아니요, 가치 유형입니다 ~ 아니다 정의에 따라 불변.

첫째, "가치 유형이 불변의 유형처럼 행동합니까?"라는 질문을 더 잘 물었을 것입니다. 그들이 불변인지 묻는 대신 - 나는 이것이 많은 혼란을 야기했다고 생각합니다.

struct MutableStruct
{
    private int state;

    public MutableStruct(int state) { this.state = state; }

    public void ChangeState() { this.state++; }
}

struct ImmutableStruct
{
    private readonly int state;

    public MutableStruct(int state) { this.state = state; }

    public ImmutableStruct ChangeState()
    {
        return new ImmutableStruct(this.state + 1);
    }
}

계속하려면 ...

유형이 변이 가능하거나 불변인지 여부를 정의하려면 해당 "유형"이 참조하는 내용을 정의해야합니다. 참조 유형의 저장 위치가 선언 될 때, 선언은 단지 다른 곳에 저장된 개체에 대한 참조를 보유하기 위해 공간을 할당하는 것입니다. 선언은 해당 실제 객체를 생성하지 않습니다. 그럼에도 불구하고, 특정 참조 유형에 대해 이야기하는 대부분의 상황에서는 참조를 보유한 저장 위치, 오히려 그 참조로 식별 된 물체. 객체에 대한 참조를 보유한 스토리지 위치에 글을 쓸 수 있다는 사실은 객체 자체가 변이 가능하다는 것을 의미하지 않습니다.

대조적으로, 값 유형의 저장 위치가 선언 될 때, 시스템은 해당 값 유형에 의해 보유 된 각 공공 또는 개인 필드에 대해 해당 스토리지 위치 중첩 스토리지 위치 내에 할당됩니다. 값 유형에 대한 모든 것은 해당 스토리지 위치에 보관됩니다. 변수를 정의하는 경우 foo 유형의 Point 그리고 두 분야, X 그리고 Y, 각각 3과 6을 유지하십시오. "인스턴스"를 정의하는 경우 Point 안에 foo 쌍의 쌍으로 필드, 그 인스턴스는 foo 변이 가능합니다. 인스턴스를 정의하는 경우 Point 로서 가치 해당 분야 (예 : "3,6")에서 개최되는 경우, 그러한 사례는 정의상 불변입니다. 해당 필드 중 하나를 변경하면 Point 다른 인스턴스를 유지합니다.

나는 값 유형의 "인스턴스"를 그들이 보유한 값보다는 필드라고 생각하는 것이 더 도움이된다고 생각합니다. 이 정의에 따르면, 돌연변이 가능한 스토리지 위치에 저장된 모든 값 유형 및 비다 값이 존재하는 모든 값은 언제나 선언 된 방법에 관계없이 변이 가능합니다. 진술 MyPoint = new Point(5,8) 새로운 인스턴스를 구성합니다 Point, 필드와 함께 X=5 그리고 Y=8, 그런 다음 돌연변이합니다 MyPoint 필드의 값을 새로 창조 된 것들로 바꾸어 Point. 구조물이 생성자 외부의 필드를 수정할 수있는 방법을 제공하지 않더라도 구조물 유형이 인스턴스가 다른 인스턴스의 내용으로 모든 필드를 덮어 쓰지 않도록 보호 할 수있는 방법은 없습니다.

또한, 돌고있는 구조물이 다른 수단을 통해 달성 할 수없는 의미론을 달성 할 수있는 간단한 예 : 가정. myPoints[] 여러 스레드에 액세스 할 수있는 단일 요소 배열이며 20 개의 스레드가 동시에 코드를 실행합니다.

Threading.Interlocked.Increment(myPoints[0].X);

만약에 myPoints[0].X 0으로 시작하고 20 스레드는 동시에 위의 코드를 수행합니다. myPoints[0].X 20과 같을 것입니다. 위의 코드를 모방하려는 경우 :

myPoints[0] = new Point(myPoints[0].X + 1, myPoints[0].Y);

그렇다면 스레드가 읽히면 myPoints[0].X 다른 스레드 사이에서 그것을 읽고 수정 된 값을 다시 작성하면 증분 결과가 손실 될 것입니다 (결과적으로 결과적으로 myPoints[0].X 1 ~ 20 사이의 값으로 임의로 끝날 수 있습니다.

물체/structs는 데이터를 변경할 수없고 반환 된 구조물이 new 구조. 전형적인 예는입니다

String s = "abc";

s.toLower();

만약 toLower 함수는 "S"를 대체하는 새 문자열이 반환되도록 작성되며, 불변이 불변하지만, "S"내부의 문자를 대체하는 문자로 문자로 문자를 보내면 "새 문자열"을 선언하지 않으면 변이 가능합니다.

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