使用反射修改泛型Dictionary条目值后字典取值未更新问题
问题解决:反射修改Dictionary Entry值后dict[key]仍返回原值的原因及修复
核心原因
你遇到的问题根源在于:.NET中Dictionary<TKey,TValue>的内部Entry是值类型(struct)。当你通过((Array)dict.GetField(...).GetValue(dict)).GetValue(0)获取entry时,得到的是该结构体的副本,而非原数组中元素的引用。因此你修改的只是这个副本的value字段,原数组里的真实Entry完全没被改动,自然通过dict[key]访问时还是原值。
修复方案
要修改原数组中的Entry,需要先获取整个entries数组,取出对应索引的结构体实例,修改其value后,再将修改后的结构体重新赋值回数组的对应位置。
修正后的测试代码
const BindingFlags BINDING_FLAGS_ALL = (BindingFlags)65535; Dictionary<string, string> dict = new Dictionary<string, string>(); dict["key1"] = "original value"; // 获取entries数组 Array entriesArray = (Array)dict.GetType().GetField("entries", BINDING_FLAGS_ALL).GetValue(dict); // 获取指定索引的Entry(值类型,此时是副本) object entry = entriesArray.GetValue(0); // 获取key和value字段 object key = entry.GetType().GetField("key", BINDING_FLAGS_ALL).GetValue(entry); FieldInfo valField = entry.GetType().GetField("value", BINDING_FLAGS_ALL); Console.WriteLine($"original value at '{key}' == '{valField.GetValue(entry)}'"); // 修改副本的value valField.SetValue(entry, "changed value!"); Console.WriteLine($"new value in copied entry == '{valField.GetValue(entry)}'"); // 将修改后的副本放回原数组 entriesArray.SetValue(entry, 0); // 现在通过dict[key]获取就能得到新值了 object val = dict[(string)key]; Console.WriteLine($"dict[{key}] == '{val}'");
输出结果
original value at 'key1' == 'original value' new value in copied entry == 'changed value!' dict[key1] == 'changed value!'
额外说明
因为你不知道字典的Key和Value类型,上述代码完全基于反射操作,不需要依赖具体的泛型类型,同样适用于任意Dictionary<TKey,TValue>实例。
内容的提问来源于stack exchange,提问作者devopsdinosaur
相关产品推荐
相关产品推荐

