我有一個linq查詢,我在foreach循環中迭代的結果。foreach和linq查詢 - 需要幫助試圖瞭解請
首先是其抓住的控件的集合從表佈局面板的查詢時,我然後遍歷集合並因此從TableLayoutPanel中刪除控件:
var AllItems = (from Item in this.tableLayoutPanel1.Controls.OfType<ItemControl>()
select Item);
foreach (ItemControl item in AllItems)
{
Trace.WriteLine("Removing " + item.ToString());
this.tableLayoutPanel1.Controls.Remove(item);
item.Dispose();
}
上面沒有做,因爲我預期的(即拋出一個錯誤),它只刪除一半的控件(ODD編號的) 看來,在每次迭代中AllItems都會減少它的自身,並且儘管正在修改底層集合,但不會引發錯誤。
如果我有一個字符串數組simmilar:
string[] strs = { "d", "c", "A", "b" };
List<string> stringList = strs.ToList();
var allitems = from letter in stringList
select letter;
foreach (string let in allitems)
{
stringList.Remove(let);
}
這一次的Visual Studio拋出抱怨底層集合已變化的情況下(如預期)。
爲什麼第一個例子不會爆炸呢?
有一些關於迭代器/ IEnumerable,我不理解這裏,我不知道是否有人可以幫助我瞭解linq和foreach在引擎蓋下發生了什麼。
(我知道我可以AllItems.ToList()治癒了這兩個問題,我以前迭代,但想明白爲什麼第二個例子中拋出一個錯誤,先不)
那是'Enumerable.OfType'通過使用延遲執行實現了這個問題不相關的事實的原因,因此序列總是在每一個枚舉變化? – 2012-07-19 17:43:44
@TimSchmelter好了,'OfType'只是列舉了通過直接使用源枚舉 - 雖然它沒有做檢查,同樣的事情會,如果你列舉的對象發生,並把內循環檢查。底層枚舉器沒有檢查控件集合是否被修改。 –
2012-07-19 17:47:30
@TimSchmelter:我懷疑所有的LINQ操作可能會從原來的職位代碼被刪除,它會表現得完全一樣的方式。正如裏德所說,這是普查員實施的結果。 OfType與它無關。 – StriplingWarrior 2012-07-19 17:51:54