foreach遍历KeyValuePair是最安全常用方式,只读时性能最优;需删元素应先收集键再批量删除;仅需键或值时直接遍历Keys/Values更高效;复杂操作用LINQ但注意性能代价。
foreach 遍历 KeyValuePair 是最安全、最常用的方式绝大多数时候,你只需要同时拿到键和值,foreach (var kvp in dict) 就是首选。它底层调用 GetEnumerator(),性能好、语义清晰、且编译器能做类型推导。
foreach (var item in dict) 后再猜 item 类型——虽然能运行,但可读性差;明确写成 KeyValuePair 或继续用 var(C# 6+ 推荐)更稳妥dict.Remove(key) 或 dict.Add(...),会立刻抛 InvalidOperationException: Collection was modified
foreach 仍是最快方式;比先转 ToList() 再 for 省内存也省时间Dictionaryages = new Dictionary { {"Alice", 25}, {"Bob", 30}, {"Charlie", 35} }; foreach (var kvp in ages) { Console.WriteLine($"Name: {kvp.Key}, Age: {kvp.Value}"); }
Keys 和 Values 属性当你确定只需要一边数据时,直接遍历 dict.Keys 或 dict.Values 更高效,避免构造无用的 KeyValuePair 对象。
dict.Keys 返回 KeyCollection,是只读视图,修改原字典后它自动反映变化foreach (string key in dict.Keys) 中若后续要用 dict[key],得确保键存在——虽然字典遍历时键必然存在,但若你在循环中删了它,下一次访问可能出错(所以还是推荐先缓存要删的键)dict.Keys.ToList() 再遍历——除非你真需要顺序或反复访问foreach (string name in ages.Keys)
{
Console.WriteLine($"Name: {name}");
}
foreach (int age in ages.Values)
{
Console.WriteLine($"Age: {age}");
}
这是新手最容易翻车的点:想删掉所有年龄小于 30 的人,结果写成 foreach 里直接 Remove,程序当场崩溃。
dict.Where(kvp => kvp.Value kvp.Key).ToList()
.ToList() —— 如果只用 .ToArray() 或不转集合,延迟执行会导致遍历时字典被改,依然报错dict.RemoveAll(kvp => kvp.Value (需引用 System.Linq),但注意这方法不是 Dictionary 原生 API,而是 LINQ 扩展,本质仍是两趟操作
var keysToRemove = ages
.Where(kvp => kvp.Value < 30)
.Select(kvp => kvp.Key)
.ToList();
foreach (string key in keysToRemove)
{
ages.Remove(key);
}
当需求超出简单遍历,比如“按值降序输出”或“多核处理大字典”,LINQ 很方便,但它会创建中间集合,有开销。
dict.OrderBy(kvp => kvp.Value) 返回 IOrderedEnumerable,不是新字典;遍历时才真正排序,但每次 fore
ach 都会重排——如需复用,加 .ToList()
Parallel.ForEach(dict.AsParallel(), ...) 适合 CPU 密集型处理(比如对每个值做哈希计算),但对简单打印或 IO 操作反而拖慢,还可能引发线程安全问题(比如共享 Console.WriteLine)dict[key]——它已经给你 kvp 了,再查一次是冗余开销var sorted = ages
.OrderByDescending(kvp => kvp.Value)
.ThenBy(kvp => kvp.Key);
foreach (var kvp in sorted)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
实际项目里,95% 的遍历场景用第一个 foreach 就够了。剩下那 5%,往往不是“怎么遍历”的问题,而是“要不要遍历”——比如是否该用索引结构、是否该提前建好视图、或者干脆换用 SortedDictionary。别让遍历逻辑掩盖了数据建模的根本问题。