/// <summary> /// Not Equals /// </summary> /// <param name="il"></param> /// <returns></returns> public static ILGenerator Cne(this ILGenerator il) { return il.Ceq().Cfalse(); }
/// <summary> /// Emit Equality Compare for 2 arguments in top of stack /// </summary> /// <param name="il"></param> /// <param name="argType"></param> /// <returns></returns> public static ILGenerator IsEquals(this ILGenerator il, Type argType) { if (argType.IsPrimitive) { return il.Ceq(); } var nulType = Nullable.GetUnderlyingType(argType); if (nulType != null) { var miGetValue = argType.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).GetGetMethod(); var miHasValue = argType.GetProperty("HasValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).GetGetMethod(); var locVar1 = il.DeclareLocal(argType); var locVar2 = il.DeclareLocal(argType); var lblHasValues = il.DefineLabel(); var lblExit = il.DefineLabel(); il .Stloc(locVar2) .Stloc(locVar1) .Ldloca(locVar1) .Call(miHasValue) .Ldloca(locVar2) .Call(miHasValue) .Add() .Dup() .Ldc_I4(2) .Beq(lblHasValues) .Ldtrue() .Xor() .Br(lblExit) .Label(lblHasValues) .Pop() .Ldloca(locVar1) .Call(miGetValue) .Ldloca(locVar2) .Call(miGetValue) .IsEquals(nulType) .Label(lblExit); return il; } var eqMethod = argType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new Type[] { argType, argType }, null); if (eqMethod != null) { return il.Call(eqMethod); } var eqType = typeof(IEquatable<>).MakeGenericType(argType); var lblEnd = il.DefineLabel(); if (!argType.IsValueType) { if (eqType.IsAssignableFrom(argType)) { var lblHasValue1 = il.DefineLabel(); var locVar2 = il.DeclareLocal(argType); il .Stloc(locVar2) .Dup() .Brtrue(lblHasValue1) .Ldloc(locVar2) // if arg1 == 0 .Ceq() // Сравниваем refernces .Br(lblEnd) .Label(lblHasValue1) .Ldloc(locVar2) .Callvirt(eqType.GetMethod("Equals")); } else { il.Ceq(); } } else { if (eqType.IsAssignableFrom(argType)) { var var1 = il.DeclareLocal(argType); il.Stloc(var1).Ldloca(var1); il.Callvirt(eqType.GetMethod("Equals")); } } il.MarkLabel(lblEnd); return il; }
/// <summary> /// Compare /// </summary> /// <param name="il"></param> /// <param name="pred"></param> /// <returns></returns> public static ILGenerator Cmp(this ILGenerator il, PredicateType pred) { switch (pred) { case PredicateType.Equal: return il.Ceq(); case PredicateType.GreaterThan: return il.Cgt(); case PredicateType.GreaterThanOrEqual: return il.Cge(); case PredicateType.LessThan: return il.Clt(); case PredicateType.LessThanOrEqual: return il.Cle(); case PredicateType.NotEqual: return il.Cne(); case PredicateType.IsFalse: return il.Cfalse(); case PredicateType.IsTrue: return il.Ctrue(); default: throw new ArgumentException(@"Invalid Predicate Type", "pred"); } }