【发布时间】:2022-01-06 03:18:48
【问题描述】:
即使在枚举过程中修改了枚举集合,以下代码也不会抛出。
using System;
using System.Collections;
using System.Runtime.CompilerServices;
namespace ConsoleApp1
{
class MyKey
{
}
class Program
{
static void Main(string[] args)
{
ConditionalWeakTable<MyKey, string> table = new();
MyKey k1 = new();
MyKey k2 = new();
MyKey k3 = new();
table.Add(k1, "v1");
table.Add(k2, "v2");
table.Add(k3, "v3");
var enumerator = ((IEnumerable)table).GetEnumerator();
while(enumerator.MoveNext()) // no exception thrown
{
Console.WriteLine(enumerator.Current);
table.Remove(k1);
table.Remove(k2);
table.Remove(k3);
}
}
}
}
[ConsoleApp1.MyKey, v1]
这是有意为之,还是偶然?如果是前者,那么在密钥被垃圾回收的情况下,什么会阻止抛出异常?
非常感谢!
【问题讨论】:
-
ConditionalWeakTable是 thread safe。这意味着在您的线程迭代集合时可能有另一个线程正在删除项目,并且它需要安全。枚举器在调用MoveNext()之间有 logic to handle entries being removed -
docs also state that 此外,它可能不会返回检索枚举器时存在的所有条目,例如,在检索枚举器之后但之前收集或删除的条目枚举 所以你可以放心地假设它是设计使然。也与提供的代码@canton7 匹配。
-
@canton7 我会接受您的评论作为答案 - 我忽略了线程安全部分。
-
很好奇为什么你认为它会抛出异常......
-
@Charlieface 因为一堆常见类型的枚举器,最著名的是
List<T>,所以呢?
标签: c# collections ienumerable