public Enumerator(XDictionary <TKey, TValue> content) { this.content = content; number = 0; index = -1; }
internal ValuesCollection(XDictionary <TKey, TValue> content, TKey key) { this.content = content; this.key = key; hashCode = content.GetHashCode(key); length = -1; }
private static void SwitchObject <T>(this ILGenerator ILGen, Action <ILGenerator> LdcValue, LocalBuilder HashCodeLocal, Action <ILGenerator> CallEquals, XDictionary <int, List <CaseInfo <T> > > Cases, Label DefaultLabel, Action <ILGenerator, T> ldcCase, int Begin, int Index, int End) { if (Begin > End) { return; } if (Begin == End) { ILGen.LoadLocal(HashCodeLocal); ILGen.LoadConstant(Cases.GetEntry(Begin).Key); ILGen.Emit(OpCodes.Bne_Un, DefaultLabel); foreach (var Item in Cases.GetEntry(Begin).Value) { LdcValue(ILGen); ldcCase(ILGen, Item.Value); CallEquals(ILGen); ILGen.Emit(OpCodes.Brtrue, Item.Label); } ILGen.Emit(OpCodes.Br, DefaultLabel); return; } if (Begin + 1 == End) { var EndLabel = ILGen.DefineLabel(); ILGen.LoadLocal(HashCodeLocal); ILGen.LoadConstant(Cases.GetEntry(Begin).Key); ILGen.Emit(OpCodes.Bne_Un, EndLabel); foreach (var Item in Cases.GetEntry(Begin).Value) { LdcValue(ILGen); ldcCase(ILGen, Item.Value); CallEquals(ILGen); ILGen.Emit(OpCodes.Brtrue, Item.Label); } ILGen.MarkLabel(EndLabel); ILGen.LoadLocal(HashCodeLocal); ILGen.LoadConstant(Cases.GetEntry(End).Key); ILGen.Emit(OpCodes.Bne_Un, DefaultLabel); foreach (var Item in Cases.GetEntry(End).Value) { LdcValue(ILGen); ldcCase(ILGen, Item.Value); CallEquals(ILGen); ILGen.Emit(OpCodes.Brtrue, Item.Label); } ILGen.Emit(OpCodes.Br, DefaultLabel); return; } var GtLabel = ILGen.DefineLabel(); ILGen.LoadLocal(HashCodeLocal); ILGen.LoadConstant(Cases.GetEntry(Index).Key); ILGen.Emit(OpCodes.Bgt, GtLabel); SwitchObject( ILGen, LdcValue, HashCodeLocal, CallEquals, Cases, DefaultLabel, ldcCase, Begin, (Begin + Index) / 2, Index); ILGen.MarkLabel(GtLabel); SwitchObject( ILGen, LdcValue, HashCodeLocal, CallEquals, Cases, DefaultLabel, ldcCase, Index + 1, (Index + 1 + End) / 2, End); }
/// <summary> /// 生成指定类型的 Switch 代码块。 /// </summary> /// <typeparam name="T">指定类型</typeparam> /// <param name="iLGen">ILGenerator IL 指令生成器</param> /// <param name="emitLdcValue">生成加载 Switch 参数的指令的委托</param> /// <param name="getHashCodeMethod">获取 HashCode 值的方法,参数签名: int(T)</param> /// <param name="equalsMethod">比例两个值的方法,参数签名: bool (T, T)</param> /// <param name="cases">case 标签块集合</param> /// <param name="defaultLabel">默认标签块</param> /// <param name="ldcCaseValue">生成加载指定 Case 块值的指定的委托</param> public static void Switch <T>(this ILGenerator iLGen, Action <ILGenerator> emitLdcValue, MethodInfo getHashCodeMethod, MethodInfo equalsMethod, CaseInfo <T>[] cases, Label defaultLabel, Action <ILGenerator, T> ldcCaseValue) { cases = (CaseInfo <T>[])cases.Clone(); if (getHashCodeMethod.IsStatic) { for (int i = 0; i < cases.Length; i++) { cases[i].HashCode = (int)getHashCodeMethod.Invoke(null, new object[] { cases[i].Value }); } } else { for (int i = 0; i < cases.Length; i++) { cases[i].HashCode = (int)getHashCodeMethod.Invoke(cases[i].Value, null); } } Array.Sort(cases); var GroupedCases = new XDictionary <int, List <CaseInfo <T> > >(); foreach (var Item in cases) { List <CaseInfo <T> > Items; GroupedCases.TryGetValue(Item.HashCode, out Items); if (Items == null) { Items = new List <CaseInfo <T> >(); Items.Add(Item); GroupedCases.Add(Item.HashCode, Items); } else { Items.Add(Item); } } var HashCodeLocal = iLGen.DeclareLocal(typeof(int)); emitLdcValue(iLGen); iLGen.Emit(OpCodes.Call, getHashCodeMethod); iLGen.StoreLocal(HashCodeLocal); SwitchObject( iLGen, emitLdcValue, HashCodeLocal, (EqILGen) => { EqILGen.Emit(OpCodes.Call, equalsMethod); }, GroupedCases, defaultLabel, ldcCaseValue, 0, (GroupedCases.Count - 1) / 2, GroupedCases.Count - 1); }