.NET中动态调用LINQ ToDictionary简化字典返回代码的方法
.NET中简化LINQ转Dictionary代码的实现方案
问题背景
编写LINQ表达式处理字典并返回Dictionary类型结果时,标准ToDictionary写法需要重复传入两个lambda表达式分别指定键、值选择器,存在冗余样板代码。目标是封装ToDictionary(<lambda key>, <lambda val>)的通用逻辑,简化书写。
场景示例
Dictionary<string, object> d_filt; Dictionary<string, object> d_in = new Dictionary<string, object>(); d_in.Add("k1", 4); d_in.Add("k2", 3); d_in.Add("k3", 2); d_in.Add("k4", 1); // 现有标准写法 d_filt = d_in.Where(p => p.value > 2) .ToDictionary(p => p.Key, p => p.Value); // 最初设想的独立辅助函数写法 d_filt = linq2Dict(d_in.Where(p => p.value > 2));
其中linq2Dict(<LinqObj>)是预期可动态调用ToDictionary方法的辅助函数。尝试过用反射实现该需求,但常规反射用法无法正确获取ToDictionary方法。
VB语言下的标准写法冗余度更高:
Dim d_filt = d_in.Where(Function(p) p.value > 2).ToDictionary(Function(p) p.Key, Function(p) p.Value)
最优实现方案
不需要使用反射做动态调用,直接实现无参的ToDict()扩展方法是最简洁、性能最优、类型安全的方案,最终写法更符合LINQ链式调用习惯:
// 最终推荐简化写法 d_filt = d_in.Where(p => p.value > 2).ToDict();
具体实现代码
using System.Collections.Generic; using System.Linq; using System; public static class EnumerableExtensions { /// <summary> /// 将KeyValuePair序列直接转换为对应字典,无需手动指定键值选择器 /// </summary> /// <exception cref="ArgumentNullException">入参为空时抛出</exception> public static Dictionary<TKey, TValue> ToDict<TKey, TValue>( this IEnumerable<KeyValuePair<TKey, TValue>> source) { if (source == null) throw new ArgumentNullException(nameof(source)); return source.ToDictionary(pair => pair.Key, pair => pair.Value); } /// <summary> /// 支持自定义键比较器的重载 /// </summary> public static Dictionary<TKey, TValue> ToDict<TKey, TValue>( this IEnumerable<KeyValuePair<TKey, TValue>> source, IEqualityComparer<TKey> keyComparer) { if (source == null) throw new ArgumentNullException(nameof(source)); return source.ToDictionary(pair => pair.Key, pair => pair.Value, keyComparer); } }
补充说明
- 反射无法直接获取
ToDictionary方法的原因是:该方法是定义在System.Linq.Enumerable静态类上的泛型扩展方法,并非IEnumerable<T>类型的实例方法,常规实例反射逻辑无法定位到该方法。 - 上述扩展方法实现没有反射带来的运行时性能损耗和类型安全风险,所有类型检查在编译期完成,兼容所有对字典做过滤、投影后返回
KeyValuePair<TKey, TValue>序列的场景。 - 相比独立封装
linq2Dict静态辅助函数,扩展方法的链式调用风格和原生LINQ方法保持一致,使用体验更流畅。
内容的提问来源于stack exchange,提问作者Timothy C. Quinn
相关产品推荐
相关产品推荐

