2012-03-14 4 views
0
   var names = new[] { 
          new { Name = "John", Age = 44 }, 
          new { Name = "Diana", Age = 45 }, 
          new { Name = "James", Age = 17 }, 
          new { Name = "Francesca", Age = 15} 
          }; 

      for (int i = 0; i < names.Length; i++) 
      { 
       names[i].Age = 23; //-------->Error 
       names[i] = new { Name = "XYX", Age = 26 }; //----->Works fine 
      } 

      foreach(var name in names) 
      { 
       name.Age = 1; //-------->Error 
       name = new { Name = "ABC", Age = 25 }; //-------->Error 
      } 

여기에 두 가지 질문이 있습니다. 1. 왜 반복 변수의 any 속성을 변경할 수 없었습니다.
2. for 루프의 반복 변수에만 새 객체를 할당 할 수있었습니다. foreach 루프가 아닙니다. 왜?foreach 루프에서 반복 변수를 변경할 수없는 이유는 무엇입니까?

답변

9

질문 1 : 왜 반복 변수의 속성을 변경할 수 없었습니까? 문서에서

Anonymous Types에 :

익명 유형의 당신은에있는 속성 값을 변경할 수 없습니다 읽기 전용 속성

의 집합을 캡슐화 할 수있는 편리한 방법을 제공하여 익명 형식이므로

name.Age = 1; 
// and 
names[i].Age = 1; 

은 똑같이 유효하지 않습니다.


질문 2. 난 단지 루프의 반복 변수에 새 개체를 할당 할 수 있었다. foreach 루프가 아닙니다. 왜? 문서에서

IEnumerable에 :

열거자는 컬렉션이 변경되지 않고 남아있는만큼 유효합니다.

어떤 방식 으로든 백업 목록을 변경하면 반복기가 무효화됩니다. 반복자가 Age 필드를 기반으로 특정 순서로 항목을 반환 한 경우 어떻게 될지 고려하십시오.

+0

참고 : 이것은 당신이 정렬 문제를 언급 할 때까지 나는 모든 당신과 함께 의견이었다 1. – Matthias

+0

를 질문에 대한 답변입니다. 지금은 이해. 고마워요! –

7

왜 반복 변수의 속성을 변경할 수 없었습니다.

익명 형식을 사용하고 있습니다. 익명 형식은 항상 C#에서 읽기 전용 속성을 사용합니다. (VB에서 그들은 기본적으로 읽기/쓰기하고 있지만 Key 수정과 읽기 전용으로 만들 수 있습니다.)를 C# 4 사양에서

섹션 7.6.10.6은 :

익명 개체 이니셜 라이저는 선언 익명 형식이며 해당 형식의 인스턴스를 반환합니다. 익명 형식은 object에서 직접 상속되는 무명 클래스 형식입니다. 익명 형식의 멤버는 해당 형식의 인스턴스를 만드는 데 사용되는 익명 개체 이니셜 라이저에서 유래 한 읽기 전용 속성 시퀀스입니다. 두 번째 질문에 대한

...

는 난 단지 루프의 반복 변수에 새 개체를 할당 할 수 있었다. foreach 루프가 아닙니다. 왜?

언어 사양은 그런 식으로 정의한다. 언어 사양은 그냥 배열에 대한 일을하게하지 않는 특히,이 변수를 변경할 수있는 경우에도, 그 배열을 변경하지 않을 것입니다. 일반적으로, foreach에만 시퀀스의 "읽기"보기를 ​​제공 IEnumerable/IEnumerator (즉처럼 보이는 또는 회원)을 사용합니다. 는 C# 4 사양의 섹션 8.8.4에서

는 :

반복 해 변수 내장 문 위에 연장 된 범위와 읽기 전용 로컬 변수에 대응한다. 그것은 단일 읽기 전용 변수 비록이 반복 될 때마다 "새로운"변수가 유효하다는 있도록

는 (중요한 것은, 반복 사이의 값을 변화. C# 5에서는이 변화 될 것이다. 차이는 경우에만 중요 변수는 람다 식 같은 의해 캡처) 질문 2로

+0

감사합니다. 특히 변수를 변경할 수 있다고하더라도 배열을 변경할 수는 없습니다. 이 변수는 원본 객체의 사본을 보유하고 있습니까? –

+1

@vaibhav : 아니요, 원본 개체에 * 참조 * 사본을 보유하고 있습니다. 배열은 참조 만 보유합니다. 배열의 값을 변경하려면 배열 내용 *을 변경해야합니다. 배열에있는 참조의 * copy * 값을 가진 변수를 변경하는 것은 아무 것도하지 않습니다. –

+0

names [i] = new object,이 문장에서, 나는 원래의 객체가 아니라 그것을 복사하고있다. –

0

).를 이용해서 반복 변수를 변경하지 않는 경우 "잘 작동"에서. 이 경우 반복 변수는 i입니다. 당신이하는 일은 배열의 한 원소를 새로운 원소로 대체하는 것입니다. 이것은 항상 작동합니다.

0

foreach는 열거자를 사용하므로 열거자는 기본 컬렉션을 변경할 수 없지만 컬렉션의 개체에서 참조하는 개체는 변경할 수 있습니다. 여기서 Value 및 Reference 유형의 의미가 작용합니다.

참조 유형 즉, 클래스에서 모든 컬렉션은 객체에 대한 참조입니다. 그와 같이, 그것은 실제로 어떤 객체의 멤버와도 접촉하지 않으며, 그것들에 대해서별로 관심을 가질 수 없다. 개체를 변경해도 컬렉션에 영향을주지 않습니다.

한편, 값 형식은 전체 구조를 컬렉션에 저장합니다. 컬렉션을 변경하고 열거자를 무효화하지 않고 멤버를 만질 수 없습니다.

또한 열거 컬렉션의 값의 사본을 돌려 준다. ref-type에서 이것은 의미가 없습니다. 참조 사본은 동일한 참조이며 변경 내용이 범위를 벗어나서 원하는 방식으로 참조 된 객체를 변경할 수 있습니다. 반면에 값 유형에서는 얻는 모든 것이 오브젝트의 사본이라는 것을 의미하므로 해당 사본의 변경 사항은 절대로 전파되지 않습니다.

관련 문제