C#的Dictionary初步讨论与更佳的使用方法
事实:不论是ArrayList,Hashtable,List<T>等几种集合,都离不开数组的实现,往简单方面理解,不妨认为这是一种"高级"的数组
首先说说List:
List<T>用起来十分方便,然而其实际上是对数组的一个包装,其要点为:List实例创建时会初始化一个数组与一个包含当前列表元素数量的标记,每当新的元素加入时标记增加1,如果数组长度不够,会重新初始化一个新的长度为原有数组2倍的新数组,再将原有数组的元素复制到新数组,然后用新的数组替代原有的数组.
接着说Dictionary,Dictionary对实际数据的维护与List的原理是类似的,不过他要同时维护两个数组,第一个数组为Key的Hash值,按照大小进行顺序排列,第二个数组为Key/Value对的数组.为了根据一个Key检索一个值,Dictionary需要首先计算Key的Hash值,根据这个Hash值计算在第二个数组中的可能位置,然后进行比较直到找到对应的值为止.
由此可以看出,Dictionary对数组的易用性优势是显而易见的,然而性能缺陷也是比较明显的,因此在进行编码时,如果二者都可以经由某种设计实现所需功能时,用数组无疑是最佳选择.
下面的代码显示了遍历一个数组与一个字典所带来的性能差异
class Program { private enum Num { one = 1, two, three, four, five, six, seven, eight } static void Main(string[] args) { int[] array = new int[]{1, 2, 3, 4, 5, 6, 7, 8}; Dictionary<Num, int> dict = new Dictionary<Num,int>() { {Num.one, 1}, {Num.two, 2}, {Num.three, 3}, {Num.four, 4}, {Num.five, 5}, {Num.six, 6}, {Num.seven, 7}, {Num.eight, 8} }; int max = 10000000; int n; Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < max; i++) { n = array[0] + array[1] + array[2] + array[3] + array[4] + array[5] + array[6] + array[7]; } sw.Stop(); Console.WriteLine(sw.Elapsed); sw.Restart(); for (int i = 0; i < max; i++) { n = dict[Num.one] + dict[Num.two] + dict[Num.three] + dict[Num.four] + dict[Num.five] + dict[Num.six] + dict[Num.seven] + dict[Num.eight]; } sw.Stop(); Console.WriteLine(sw.Elapsed); sw.Restart(); for (int i = 0; i < max; i++) { n = array[(int)Num.one - 1] + array[(int)Num.two - 1] + array[(int)Num.three - 1] + array[(int)Num.four - 1] + array[(int)Num.five - 1] + array[(int)Num.six - 1] + array[(int)Num.seven - 1] + array[(int)Num.eight - 1]; } sw.Stop(); Console.WriteLine(sw.Elapsed); Console.ReadLine(); } }
输出:
00:00:00.1069296
00:00:01.5431100
00:00:00.1066442
------------------------------------------------
问题:使用数组存储数据当然性能较好,但是没有Key信息,索引也不好理解,也不易于扩展,怎么办
理解的问题可以通过定义常量解决
本文举例介绍一种某些情形下可以结合Enum解决的方案,在Key选项有限的情形下这种方式既照顾了性能,又易于阅读与扩展.
代码1:Enum定义
/// <summary> /// 物品类型 /// </summary> public enum ItemType { /// <summary> /// 未知 /// </summary> None = 0, /// <summary> /// 头盔 /// </summary> Helmet = 1, /// <summary> /// 项链 /// </summary> Necklace = 2, /// <summary> /// 护肩 /// </summary> Shoulder = 3, /// <summary> /// 盔甲 /// </summary> Amor = 4, /// <summary> /// 手套 /// </summary> Gloves = 5, /// <summary> /// 腰带 /// </summary> Belt = 6, /// <summary> /// 戒指 /// </summary> Ring = 7, /// <summary> /// 裤子 /// </summary> Trousers = 8, /// <summary> /// 靴子 /// </summary> Boots = 9, /// <summary> /// 单手剑 /// </summary> OneHandSword = 10, /// <summary> /// 双手剑 /// </summary> TwoHandSword = 11, /// <summary> /// 单手杖 /// </summary> OneHandStaff = 12, /// <summary> /// 双手杖 /// </summary> TwoHandStaff = 13, /// <summary> /// 单手斧 /// </summary> OneHandAxe = 14, /// <summary> /// 双手斧 /// </summary> TwoHandAxe = 15, /// <summary> /// 弓 /// </summary> Bow = 16, /// <summary> /// 弩枪 /// </summary> OneHandCrossBow = 17, /// <summary> /// 双手弩 /// </summary> TwoHandCrossBow = 18, /// <summary> /// 标枪 /// </summary> Javelin = 19, /// <summary> /// 长矛 /// </summary> Spear = 20, /// <summary> /// 匕首 /// </summary> Dagger = 21, /// <summary> /// 单手锤 /// </summary> OneHandHammer = 22, /// <summary> /// 双手锤 /// </summary> TwoHandHammer = 23, /// <summary> /// 盾牌 /// </summary> Shield = 24, /// <summary> /// 魔法书 /// </summary> MagicBook = 25, /// <summary> /// 魔法球 /// </summary> MagicBall = 26, /// <summary> /// 箭袋 /// </summary> Quiver = 27 }
代码2:数据的存储
WorkShops = new IItemWorkshop[(Enum.GetValues(typeof(ItemType)) as int[]).Max() + 1]; WorkShops[(int)ItemType.Helmet] = new DefenceItemWorkshop<Helmet>(); WorkShops[(int)ItemType.Necklace] = new ItemWorkshop<Necklace>(); WorkShops[(int)ItemType.Shoulder] = new DefenceItemWorkshop<Shoulder>(); WorkShops[(int)ItemType.Amor] = new DefenceItemWorkshop<Amor>(); WorkShops[(int)ItemType.Gloves] = new DefenceItemWorkshop<Gloves>(); WorkShops[(int)ItemType.Belt] = new DefenceItemWorkshop<Belt>(); WorkShops[(int)ItemType.Ring] = new ItemWorkshop<Ring>(); WorkShops[(int)ItemType.Trousers] = new DefenceItemWorkshop<Trousers>(); WorkShops[(int)ItemType.Boots] = new DefenceItemWorkshop<Boots>(); WorkShops[(int)ItemType.OneHandSword] = new WeaponItemWorkshop<OneHandSword>(); WorkShops[(int)ItemType.TwoHandSword] = new WeaponItemWorkshop<TwoHandSword>(); WorkShops[(int)ItemType.OneHandStaff] = new WeaponItemWorkshop<OneHandStaff>(); WorkShops[(int)ItemType.TwoHandStaff] = new WeaponItemWorkshop<TwoHandStaff>(); WorkShops[(int)ItemType.OneHandAxe] = new WeaponItemWorkshop<OneHandAxe>(); WorkShops[(int)ItemType.TwoHandAxe] = new WeaponItemWorkshop<TwoHandAxe>(); WorkShops[(int)ItemType.Bow] = new ItemWorkshop<Bow>(); WorkShops[(int)ItemType.OneHandCrossBow] = new WeaponItemWorkshop<OneHandCrossBow>(); WorkShops[(int)ItemType.TwoHandCrossBow] = new WeaponItemWorkshop<TwoHandCrossBow>(); WorkShops[(int)ItemType.Javelin] = new WeaponItemWorkshop<Javelin>(); WorkShops[(int)ItemType.Spear] = new WeaponItemWorkshop<Spear>(); WorkShops[(int)ItemType.Dagger] = new WeaponItemWorkshop<Dagger>(); WorkShops[(int)ItemType.OneHandHammer] = new WeaponItemWorkshop<OneHandHammer>(); WorkShops[(int)ItemType.TwoHandHammer] = new WeaponItemWorkshop<TwoHandHammer>(); WorkShops[(int)ItemType.Shield] = new ShieldItemWorkshop(); WorkShops[(int)ItemType.MagicBook] = new ItemWorkshop<MagicBook>(); WorkShops[(int)ItemType.MagicBall] = new ItemWorkshop<MagicBall>(); WorkShops[(int)ItemType.Quiver] = new ItemWorkshop<Quiver>();