コード例 #1
0
        private static void EmitNullableToNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked, ILocalCache locals)
        {
            Debug.Assert(typeFrom.IsNullableType());
            Debug.Assert(typeTo.IsNullableType());
            Label        labIfNull;
            Label        labEnd;
            LocalBuilder locFrom = locals.GetLocal(typeFrom);

            il.Emit(OpCodes.Stloc, locFrom);
            LocalBuilder locTo = locals.GetLocal(typeTo);

            // test for null
            il.Emit(OpCodes.Ldloca, locFrom);
            il.EmitHasValue(typeFrom);
            labIfNull = il.DefineLabel();
            il.Emit(OpCodes.Brfalse_S, labIfNull);
            il.Emit(OpCodes.Ldloca, locFrom);
            locals.FreeLocal(locFrom);
            il.EmitGetValueOrDefault(typeFrom);
            Type nnTypeFrom = typeFrom.GetNonNullableType();
            Type nnTypeTo   = typeTo.GetNonNullableType();

            il.EmitConvertToType(nnTypeFrom, nnTypeTo, isChecked, locals);
            // construct result type
            ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });

            il.Emit(OpCodes.Newobj, ci);
            il.Emit(OpCodes.Stloc, locTo);
            labEnd = il.DefineLabel();
            il.Emit(OpCodes.Br_S, labEnd);
            // if null then create a default one
            il.MarkLabel(labIfNull);
            il.Emit(OpCodes.Ldloca, locTo);
            il.Emit(OpCodes.Initobj, typeTo);
            il.MarkLabel(labEnd);
            il.Emit(OpCodes.Ldloc, locTo);
            locals.FreeLocal(locTo);
        }
コード例 #2
0
        private static void EmitNullableToNonNullableStructConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked, ILocalCache locals)
        {
            Debug.Assert(typeFrom.IsNullableType());
            Debug.Assert(!typeTo.IsNullableType());
            Debug.Assert(typeTo.GetTypeInfo().IsValueType);
            LocalBuilder locFrom = locals.GetLocal(typeFrom);

            il.Emit(OpCodes.Stloc, locFrom);
            il.Emit(OpCodes.Ldloca, locFrom);
            locals.FreeLocal(locFrom);
            il.EmitGetValue(typeFrom);
            Type nnTypeFrom = typeFrom.GetNonNullableType();

            il.EmitConvertToType(nnTypeFrom, typeTo, isChecked, locals);
        }
コード例 #3
0
        private static void EmitNonNullableToNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked, ILocalCache locals)
        {
            Debug.Assert(!typeFrom.IsNullableType());
            Debug.Assert(typeTo.IsNullableType());
            LocalBuilder locTo    = locals.GetLocal(typeTo);
            Type         nnTypeTo = typeTo.GetNonNullableType();

            il.EmitConvertToType(typeFrom, nnTypeTo, isChecked, locals);
            ConstructorInfo ci = typeTo.GetConstructor(new Type[] { nnTypeTo });

            il.Emit(OpCodes.Newobj, ci);
            il.Emit(OpCodes.Stloc, locTo);
            il.Emit(OpCodes.Ldloc, locTo);
            locals.FreeLocal(locTo);
        }
コード例 #4
0
        /// <summary>
        /// Emits default(T)
        /// Semantics match C# compiler behavior
        /// </summary>
        internal static void EmitDefault(this ILGenerator il, Type type, ILocalCache locals)
        {
            switch (type.GetTypeCode())
            {
            case TypeCode.DateTime:
                il.Emit(OpCodes.Ldsfld, DateTime_MinValue);
                break;

            case TypeCode.Object:
                if (type.GetTypeInfo().IsValueType)
                {
                    // Type.GetTypeCode on an enum returns the underlying
                    // integer TypeCode, so we won't get here.
                    Debug.Assert(!type.GetTypeInfo().IsEnum);

                    // This is the IL for default(T) if T is a generic type
                    // parameter, so it should work for any type. It's also
                    // the standard pattern for structs.
                    LocalBuilder lb = locals.GetLocal(type);
                    il.Emit(OpCodes.Ldloca, lb);
                    il.Emit(OpCodes.Initobj, type);
                    il.Emit(OpCodes.Ldloc, lb);
                    locals.FreeLocal(lb);
                    break;
                }

                goto case TypeCode.Empty;

            case TypeCode.Empty:
            case TypeCode.String:
            case TypeCode.DBNull:
                il.Emit(OpCodes.Ldnull);
                break;

            case TypeCode.Boolean:
            case TypeCode.Char:
            case TypeCode.SByte:
            case TypeCode.Byte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            case TypeCode.UInt32:
                il.Emit(OpCodes.Ldc_I4_0);
                break;

            case TypeCode.Int64:
            case TypeCode.UInt64:
                il.Emit(OpCodes.Ldc_I4_0);
                il.Emit(OpCodes.Conv_I8);
                break;

            case TypeCode.Single:
                il.Emit(OpCodes.Ldc_R4, default(float));
                break;

            case TypeCode.Double:
                il.Emit(OpCodes.Ldc_R8, default(double));
                break;

            case TypeCode.Decimal:
                il.Emit(OpCodes.Ldsfld, Decimal_Zero);
                break;

            default:
                throw ContractUtils.Unreachable;
            }
        }