例如:
1.
foreach (var item in myDic)
{
if (item.value == 42)
myDic.remove(item.key);
}
Run Code Online (Sandbox Code Playgroud)
无论内括号中的语句如何影响,迭代器都能正常工作myDic吗?
2.
var newDic = myDic.where(x=>x.value!=42).ToDictionary(x=>x.key,x=>x.value);
Run Code Online (Sandbox Code Playgroud)
第二种方法是一种好的做法吗?函数式编程和不可变?
mqp*_*mqp 29
第一种方法将在运行时崩溃,因为枚举器确保在枚举时没有人从底层集合中删除.
第二种方法是一个很好的想法,但C#字典是可变的,如果你可以用变异完成同样的事情,那么复制它们既不惯用也不高效.
这是一种典型的方式:
var itemsToRemove = myDic.Where(f => f.Value == 42).ToArray();
foreach (var item in itemsToRemove)
myDic.Remove(item.Key);
Run Code Online (Sandbox Code Playgroud)
编辑:在评论中回答您的问题.以下是您的其他问题中的示例:
myList = myList.where(x=>x>10).select(x=>x-10);
Run Code Online (Sandbox Code Playgroud)
这行代码没有运行任何东西; 它完全是懒惰的.让我们说,为了论证,我们有一个foreach后来使它看起来更像这个问题的例子.
foreach (int n in myList)
Console.WriteLine(n);
Run Code Online (Sandbox Code Playgroud)
执行时,这是每次迭代时会发生的事情:
MoveNext调查员Current属性设置为该值Current属性绑定到变量nConsole.WriteLine它你可以看到没有神秘感,也没有无限循环而没有任何东西.
现在比较我的例子,假设我们遗漏了ToArray.
var itemsToRemove = myDic.Where(f => f.Value == 42);
foreach (var item in itemsToRemove)
myDic.Remove(item.Key);
Run Code Online (Sandbox Code Playgroud)
MoveNext调查员Current属性设置为该值Current属性绑定到变量itemRemove它这不起作用,因为虽然WriteLine当你打开一个枚举器时它对集合中的某些内容完全没问题,但是当你打开一个枚举器时,你不允许Remove从集合中获取某些内容.
如果你ToArray在前面调用,那么你首先要枚举字典并填充数组.当我们到达时foreach,该foreach语句在数组上打开一个枚举器,而不是字典.在迭代数组时,您可以从字典中删除.
Joh*_*ohn 13
根据文档,从 .NET Core 3.0 开始,删除元素将不再影响活动枚举器。您可以在迭代时安全地删除项目:
foreach (var item in myDic)
{
if (item.Value == 42)
myDic.Remove(item.Key);
}
Run Code Online (Sandbox Code Playgroud)
Dictionary<TKey,TValue>.Remove 方法
仅限 .NET Core 3.0+:可以安全地调用此变异方法,而无需使 Dictionary<TKey,TValue> 实例上的活动枚举器失效。这并不意味着线程安全。
您还可以遍历集合的副本:
foreach (var item in myDic.ToList())
{
if (item.value == 42)
myDic.remove(item.key);
}
Run Code Online (Sandbox Code Playgroud)
声明myDic.ToList()中的通知foreach.
| 归档时间: |
|
| 查看次数: |
20780 次 |
| 最近记录: |