这似乎应该得到回答,但我发现潜在的欺骗行为正在问不同的事情......
我注意到这似乎工作正常(sourceDirInclusion很简单Dictionary<X,Y>)
foreach (string dir in sourceDirInclusion.Keys)
{
if (sourceDirInclusion[dir] == null)
sourceDirInclusion.Remove(dir);
}
Run Code Online (Sandbox Code Playgroud)
这是否意味着从集合中删除项目foreach是安全的,还是我很幸运?
如果我在字典中添加更多元素而不是删除呢?
我试图解决的问题是,sourceDirInclusion最初居住,但后来每个值可以在第二遍促进新项目的字典.例如,我想做的是:
foreach (string dir in sourceDirInclusion.Keys)
{
X x = sourceDirInclusion[dir];
sourceDirInclusion.Add(X.dir,X.val);
}
Run Code Online (Sandbox Code Playgroud)
简短回答:这不安全.
答案很长:来自IEnumerator<T>文档:
只要集合保持不变,枚举器仍然有效.如果对集合进行了更改(例如添加,修改或删除元素),则枚举数将无法恢复,并且其行为未定义.
请注意,文档说行为是未定义的,这意味着它可能有效,也可能不行.永远不要依赖未定义的行为.
在这种情况下,它取决于Keys可枚举的行为,关于它是否在您开始枚举时创建键列表的副本.在这个特定的情况下,我们从文档中知道返回值Dictionary<,>.Keys是一个引用回字典的集合:
返回
Dictionary<TKey, TValue>.KeyCollection的不是静态副本; 相反,Dictionary<TKey, TValue>.KeyCollection指回原始的键Dictionary<TKey, TValue>.因此,改变Dictionary<TKey, TValue>继续得到体现Dictionary<TKey, TValue>.KeyCollection.
因此,在枚举字典的键时修改字典应该被认为是不安全的.
您可以通过一次更改来纠正此问题.改变这一行:
foreach (string dir in sourceDirInclusion.Keys)
Run Code Online (Sandbox Code Playgroud)
对此:
foreach (string dir in sourceDirInclusion.Keys.ToList())
Run Code Online (Sandbox Code Playgroud)
该ToList()扩展方法将创建密钥列表中的一个明确的副本,使它修改字典安全; "基础集合"将是副本而不是原始副本.
| 归档时间: |
|
| 查看次数: |
210 次 |
| 最近记录: |