private static MethodBuilder EmitTupleEquality(TupleType tupleType, TypeBuilder typeBuilder, Dictionary<Name, FieldInfo> fieldsByID)
{
var equalityMethod = typeBuilder.DefineMethod("op_Equality", MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(bool), new System.Type[] { typeBuilder, typeBuilder });
var il = equalityMethod.GetILGenerator();
var end = il.DefineLabel();
foreach (var keyItem in tupleType.GetKeyAttributes())
{
var field = fieldsByID[keyItem];
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, field);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldfld, field);
var fieldEqualityMethod = field.FieldType.GetMethod("op_Equality", new System.Type[] { field.FieldType, field.FieldType });
if (fieldEqualityMethod != null)
il.EmitCall(OpCodes.Call, fieldEqualityMethod, null);
else
il.Emit(OpCodes.Ceq);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Brfalse_S, end);
il.Emit(OpCodes.Pop);
}
il.Emit(OpCodes.Ldc_I4_1); // True
il.MarkLabel(end);
il.Emit(OpCodes.Ret);
return equalityMethod;
}