我熟悉在使用foreach
循環(即「System.InvalidOperationException:集合已被修改」)循環時修改集合的問題。然而,當我使用Linq創建一個從字典中刪除的鍵列表,然後遍歷我的新列表時,我得到相同的異常,這對我沒有任何意義。使用Linq生成要從另一個集合中刪除的東西的集合
代碼之前,拋出一個異常:後
IEnumerable<Guid> keysToDelete = _outConnections.Where(
pair => pair.Value < timeoutPoint
).Select(pair => pair.Key);
foreach (Guid key in keysToDelete)
{
...some stuff not dealing with keysToDelete...
_outConnections.Remove(key);
}
碼,即工作:
List<Guid> keysToDelete = _outConnections.Where(
pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();
for (int i=keysToDelete.Count-1; i>=0; i--)
{
Guid key = keysToDelete[i];
...some stuff not dealing with keysToDelete...
_outConnections.Remove(key);
}
這是爲什麼?我有這樣的感覺,也許我的Linq查詢不是真的返回一個新的集合,而是原始集合的一部分,因此它指責我修改集合keysToDelete
,當我從_outConnections
中刪除元素時。
更新:以下修復也適用,由於亞當·羅賓遜:
List<Guid> keysToDelete = _outConnections.Where(
pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();
foreach (Guid key in keysToDelete)
{
...some stuff not dealing with keysToDelete...
_outConnections.Remove(key);
}
如果我能告訴人們關於LINQ查詢的一件事情,那就是查詢表達式的結果是*查詢本身*,而不是*查詢的結果*。這種常見的誤解是有關StackOverflow上關於LINQ的很大一部分問題的基礎。 – 2009-10-09 17:14:39
當我發現Linq時,我想「嘿,這讓我做了像Ruby一樣的東西!」,而且我仍然在內部按照Ruby的'map'和'select'的方式考慮像'Select'和'Where'這樣的方法,它處理並返回一個新的結果集合。我將不得不從精神上將Ruby方法與類似的Linq方法分離開來。 – 2009-10-09 17:33:25