2009-04-15 2 views
6

어제는 다음과 같은 C# 코드 (읽기 쉽도록 축소되었습니다)를 작성했습니다.for 루프에서 linq IEnumerable의 요소를 변경할 수없는 이유는 무엇입니까?

 var timeObjects = (from obj in someList 
        where (obj.StartTime != null) 
        select new MyObject() 
        { 
         StartTime= obj.StartTime.Value, 
         EndTime = obj.EndTime 
        }) 

따라서 각 항목에는 startTime이 있고 일부에는 EndTime이 있습니다 (다른 항목은 EndTime으로 null 임).

시작 시간과 종료 시간이 모두 알려지면 경과 시간을 계산하고 싶습니다.

foreach (var item in timeObjects) 
{ 
    if (item.EndTime == null) 
    { 
     item.elapsed = 0; 
    } 
    else 
    { 
     item.elapsed = (item.EndTime.Value - item.StartTime).Minutes; 
    } 
} 

그러나 이것은 작동하지 않습니다! timeObjects 콜렉션은 절대로 변경되지 않습니다.

내가 말하는 경우 :

 var timeObjects = (from obj in someList 
        where (obj.StartTime != null) 
        select new MyObject() 
        { 
         StartTime= obj.StartTime.Value, 
         EndTime = obj.EndTime 
        }).ToList(); 

foreach (var item in timeObjects) 
{ 
    if (item.EndTime == null) 
    { 
     item.elapsed = 0; 
    } 
    else 
    { 
     item.elapsed = (item.EndTime.Value - item.StartTime).Minutes; 
    } 
} 
//(only change is the ToList() at the end of the linq statement) 

그것은 작동하지 않습니다.

이것이 왜 있는지 알고 싶습니다.

답변

11

귀하의 timeObjects은 지연 실행 가능한 열거 형입니다. 목록을 두 번 열거하면 실제로 결과가 두 번 평가되어 새 개체가 만들어집니다.

ToList()를 수행하면 해당 쿼리/열거 가능 결과의 로컬 복사본이 만들어 졌으므로 변경 내용을 확인한 것입니다. 이러한 종류의 LINQ 쿼리는 커버 아래에 어떤 종류의 목록도 만들지 않습니다. 쿼리 자체는 열거 할 때까지 수행되지 않습니다. (from ... select) 상태에서 수행중인 모든 작업이 쿼리 정의를 작성하고 있습니다.

1

원래 timeObjects 정의는 lazy로 평가되는 LINQ 표현식을 정의하므로 timeObjects 열거 형을 검토 할 때마다 MyObject의 새 인스턴스가 만들어집니다.

-1

ToList()를 호출 할 때까지는 IEnumerable이 아니지만 IQueryable이므로 임시 개체가 변경됩니다.

관련 문제