键唯一为何静态类Define初始化时抛出重复键添加异常?
问题
调用Define类的任意内容时,总会触发System.TypeInitializationException异常,内部错误为ArgumentException: "An item with the same key has already been added. Key: Key1"。明明Pair1和Pair2的键是唯一的,也没有代码修改字典,却必然抛出重复键的异常,请问问题原因是什么?
代码示例
public static class Define { public static readonly Dictionary<DefineChoices, string> Definitions = new([Pair1, Pair2]); public enum DefineChoices { Key1, Key2 } public static readonly KeyValuePair<DefineChoices, string> Pair1 = new(DefineChoices.Key1, "string1"); public static readonly KeyValuePair<DefineChoices, string> Pair2 = new(DefineChoices.Key2, "string2"); }
堆栈跟踪
Unhandled exception. System.TypeInitializationException: The type initializer for 'Program.Namespace.Define' threw an exception. ---> System.ArgumentException: "An item with the same key has already been added. Key: Key1" at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at System.Collections.Generic.Dictionary`2.AddRange(IEnumerable`1 enumerable) at System.Collections.Generic.Dictionary`2..ctor(IEnumerable`1 collection, IEqualityComparer`1 comparer) at System.Collections.Generic.Dictionary`2..ctor(IEnumerable`1 collection) at Program.Namespace.Define..cctor() in FilePath\Define.cs:line 2 --- End of inner exception stack trace ---
原因分析
问题出在静态字段的初始化顺序上:
- C#规定,类的静态字段会按照它们在代码中声明的先后顺序完成初始化,而非使用顺序。
- 这里
Definitions字段声明在Pair1、Pair2和枚举DefineChoices之前,所以初始化Definitions时,后三者还未被赋值,会使用默认值。 KeyValuePair<TKey, TValue>是值类型,默认初始化时:枚举DefineChoices的默认值为0(对应Key1),字符串默认值为null。此时Pair1和Pair2的实际值都是new KeyValuePair<DefineChoices, string>(DefineChoices.Key1, null)。- 用这两个键重复的键值对初始化字典,必然触发重复键的
ArgumentException,进而导致类型初始化失败,抛出TypeInitializationException。
修复方案
调整静态字段的声明顺序,将枚举和键值对字段放在字典之前:
public static class Define { public enum DefineChoices { Key1, Key2 } public static readonly KeyValuePair<DefineChoices, string> Pair1 = new(DefineChoices.Key1, "string1"); public static readonly KeyValuePair<DefineChoices, string> Pair2 = new(DefineChoices.Key2, "string2"); public static readonly Dictionary<DefineChoices, string> Definitions = new([Pair1, Pair2]); }
内容的提问来源于stack exchange,提问作者user21161268
相关产品推荐
相关产品推荐

