2012-10-29 25 views
6

所以,這是一個非常簡單的,我認爲。塗改對象是影響對象的早期版本在foreach循環

這裏是我的代碼:

Dictionary<int, IEnumerable<SelectListItem>> fileTypeListDict = new Dictionary<int, IEnumerable<SelectListItem>>(); 

foreach (PresentationFile pf in speakerAssignment.FKPresentation.PresentationFiles) 
{ 
    IEnumerable<SelectListItem> fileTypes = Enum.GetValues(typeof(PresentationFileType)) 
       .Cast<PresentationFileType>().Select(x => new SelectListItem 
     { 
      Text = x.ToString(), 
      Value = Convert.ToString((int)x), 
      Selected = pf.Type == (int)x 
     }); 

     fileTypeListDict.Add(pf.ID, fileTypes); 
} 

正在發生的事情是,在年底的詞典將擁有所有正確的鍵,但所有值將被設置爲最後的迭代過程中創建的fileTypes列表的循環。我確信這與用作參考的對象有關,但在使用C#的時候並沒有看到過這個問題。任何人都在意解釋爲什麼會發生這種情況,我應該如何解決這個問題?

謝謝!

回答

9

這是臭名昭着的「foreach捕獲問題」,在C#5中是「固定的」(「fixed」是一個強詞,因爲它表明它以前是一個「bug」:實際上 - 現在規範已更改承認這是造成混淆的常見原因)。在兩種情況下,拉姆達捕獲可變pf「的的pf這個迭代期間值」 - 但在C#之前-5可變pf技術上作用域環路(所以只有它們中的一個,週期),其中,如在C#5和可變以上的作用域確定內部環路(所以有一個不同的變量,用於捕獲的目的,每次迭代)。

在C#4,只是騙:

foreach (PresentationFile tmp in speakerAssignment.FKPresentation.PresentationFiles) 
{ 
    PresentationFile pf = tmp; 
    //... as before 

現在pfforeach內部範圍的,它會工作確定。不這樣做,只有一個pf - 因爲你已經推遲執行,直到年底,單pf將是最後一次迭代。

一種替代的解決將是:不要推遲執行:

fileTypeListDict.Add(pf.ID, fileTypes.ToList()); // note the ToList 

現在則評價pf是「當前」,所以會產生預期的效果。

+0

我欣賞的快速和全面的解釋。祝你有美好的一天! – PFranchise