为Wrapper结构体实现集合初始化器并避免IEnumerator<T>装箱
问题解决方案
一、解决枚举器装箱问题
你的代码中,强类型GetEnumerator返回了接口类型IEnumerator<KeyValuePair<string, string>>,而Dictionary<TKey,TValue>.Enumerator是值类型,返回接口时会触发装箱。解决核心是让Wrapper直接返回值类型枚举器,同时显式实现接口方法:
public readonly struct Wrapper : IEnumerable<KeyValuePair<string, string>> { public Dictionary<string, string> Instance { get; } public Wrapper() { Instance = new Dictionary<string, string>(); } public void Add(string key, string value) { Instance.Add(key, value); } // 直接返回值类型枚举器,避免foreach场景下的装箱 public Dictionary<string, string>.Enumerator GetEnumerator() { return Instance.GetEnumerator(); } // 显式实现泛型接口的GetEnumerator,仅在强制转换为接口时触发装箱(极少场景) IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator() { return GetEnumerator(); } // 显式实现非泛型接口的GetEnumerator IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<KeyValuePair<string, string>>)this).GetEnumerator(); } }
这样修改后:
- 使用
foreach遍历Wrapper实例时,编译器会优先调用返回值类型的GetEnumerator方法,完全避免装箱。 - 只有将Wrapper强制转换为
IEnumerable<KeyValuePair<string, string>>或IEnumerable接口后调用枚举器,才会触发装箱,这类场景通常很少见。
二、集合初始化器的使用
你的代码已经包含Add(string key, string value)方法,且默认构造会初始化空字典,因此可以直接使用集合初始化语法:
var wrapper = new Wrapper { {"Key1", "Value1"}, {"Key2", "Value2"} };
编译器会自动生成“调用默认构造 → 依次调用Add方法”的代码,满足你的需求。
注意:Wrapper是readonly结构体,但Instance是引用类型,修改Instance的内容(如调用Add)是允许的,readonly仅限制Instance字段本身的引用不能被重新赋值。
内容的提问来源于stack exchange,提问作者JohanP
相关产品推荐
相关产品推荐

