2009-03-26 2 views
0

나는이 소리가 어리석은 것을 안다. 하지만 여기서 뭔가 잘못하고있을거야.목록의 구조체에서 상태를 변경할 수없는 이유는 무엇입니까?

말, 그런 곳

struct lala 
{ 
    private bool state1; 

    public lala(bool state1) 
    { 
     this.state1 = state1; 
    } 

    public void SetState1ToTrue() 
    { 
     this.state1 = true; 
    } 

    public bool GetState1() 
    { 
     return this.state1; 
    } 
} 

...

List<lala> lalas = new List<lala>(); 

lalas.Add(new lala(false)); 
lalas.Add(new lala(false)); 

lalas[0].SetState1ToTrue(); 

// Why is it False??? 
Console.WriteLine(lalas[0].GetState1()); 

가로 변경을 제외하고이에 대한 해결 방법이 있습니다, 끔찍한 unelegant 낭비 보았다

List<lala> lalas = new List<lala>(); 

lalas.Add(new lala(false)); 
lalas.Add(new lala(false)); 

lala newLala = lalas[0]; 
newLala.SetState1ToTrue(); 
lalas[0] = newLala; 

// It's True, finally. 
Console.WriteLine(lalas[0].GetState1()); 

2 줄의 코드. Linq-ish 또는 Functional Programming-ish 방법이 있다면 코드 줄이 멋지게 될 것입니다.

+0

-1 (커뮤니티 위키) – Samuel

답변

6

문제점은이 라인이다. 따라서 SetState1ToTrue는 즉시 폐기되는 lala에서 작동하며 목록의 항목은 그대로 유지됩니다. 당신은 클래스가 아닌 구조체 라라을하면 그 다음 참조 형식 (명시 적 또는 암시) 임시 변수가되는 목록 내에서 라라에 대한 참조가되도록

lala newLala = lalas[0]; 
newLala.SetState1ToTrue(); 

: 그것은이 일을 같은입니다 .

+0

+1. 전에이 문제를 겪었지만 이러한 유형의 상황을 일으키는 정확한 의미를 기억하지 못했습니다.이것은 정확히 여기서 일어나는 일입니다. 이렇게하려면 원하는 상태로 새 값을 만들어 lalas [0]에 저장해야합니다. – jdmichal

0

참조 유형 인 클래스가 아닌 값 유형 인 구조체를 다루는 것이 문제입니다. 기대하는 동작은 참조 유형의 동작입니다. 선언을 클래스로 변경하는 것이 좋습니다 (간단한 예제 만 제공). 문제가 없어야합니다.

lalas[0].SetState1ToTrue(); 

첫 번째 부분은 lalas [0] 목록에서 제 라라를 검색하고, 암시 적 변수에 새로운 복사본으로 그렇게 :

1

구조체는 값 형식이므로 값으로 전달됩니다. 즉, lalas [0]은 lalas에 구조체의 복사본을 제공합니다. 사본을 변경하려고하므로 원본은 변경되지 않습니다.

0

struct은 항상 값 유형이므로 본질적으로 변경할 수 없습니다. 이 대신 일을 의미

lalas[0].SetState1ToTrue(); 

당신이해야 할 :

lalas[0] = lalas[0].SetState1ToTrue(); 

상세 값 타입과 참조 타입의 차이점을 설명하는 excellent article by Jon Skeet 있습니다.

0

당신이 요청한 Linq-ish 접근법은 구조체를 불변으로 만들 것이므로 "상태 변경"방식 대신 수정 된 버전을 반환합니다. 그렇게하면 잘못 사용할 수 없습니다.

struct lala 
{ 
    private readonly bool state1; // note: readonly 

    public lala(bool state1) 
    { 
     this.state1 = state1; 
    } 

    public lala SetState1ToTrue() 
    { 
     return new lala(true); // would copy any other fields, unchanged 
    } 

    public bool GetState1() 
    { 
     return this.state1; 
    } 
} 

그런 다음 "변경"한 번에 전체 목록 수 :

정말 당신이 새로운 목록을 만든 있지만
List<lala> changed = original.Select(l => l.SetState1ToTrue()).ToList(); 

-하지만 당신을 위해 구조체를합니다.

+0

나는 마지막 포인트에 동의하지 않아야한다. 구조체라는 사실은 당신의 마지막 스 니펫이 새로운리스트를 만드는 것과 아무런 관련이 없다. – Samuel

+0

나는 그것을 아주 명확하게 설명하지는 않았다 - 나는 목록뿐만 아니라 목록의 모든 항목이 새로운 것을 의미한다. 수업에 참여했다면 목록에있는 각 항목을 바꿀 수 있습니다. –

+0

이것은 꽤 실행 가능한 솔루션처럼 보입니다. 느린면에서 약간의 성능을 기대하지만. 그것이 내가 걱정하지 않는다 : p. –

관련 문제