예제 #1
0
        /// <summary>
        /// 当指定的本地变量值为该类型的默认值时跳到指定块。
        /// </summary>
        /// <param name="ilGen">ilGen</param>
        /// <param name="local">本地变量</param>
        /// <param name="label">代码块</param>
        public static void BranchDefaultValue(this ILGenerator ilGen, LocalBuilder local, Label label)
        {
            var type = local.LocalType;

            if (type.IsClass ||
                type.IsInterface ||
                type.IsPointer ||
                type.IsByRef ||
                type == typeof(IntPtr) ||
                type == typeof(UIntPtr))
            {
                ilGen.LoadLocal(local);
                ilGen.BranchFalse(label);

                return;
            }

            switch (Type.GetTypeCode(type))
            {
            case TypeCode.Boolean:
            case TypeCode.Char:
            case TypeCode.SByte:
            case TypeCode.Byte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            case TypeCode.UInt32:
            case TypeCode.Single:
            case TypeCode.Int64:
            case TypeCode.UInt64:
            case TypeCode.Double:
                ilGen.LoadLocal(local);
                ilGen.BranchFalse(label);
                return;
            }

            var size = TypeHelper.SizeOf(type);

            var labNotEmpty = ilGen.DefineLabel();

            while (size >= 4)
            {
                size -= 4;
                ilGen.LoadLocalAddress(local);

                if (size != 0)
                {
                    ilGen.LoadConstant(size);
                    ilGen.Emit(OpCodes.Add);
                }

                ilGen.Emit(OpCodes.Ldind_I4);
                ilGen.BranchTrue(labNotEmpty);
            }

            if (size >= 2)
            {
                size -= 2;
                ilGen.LoadLocalAddress(local);

                if (size != 0)
                {
                    ilGen.LoadConstant(size);
                    ilGen.Emit(OpCodes.Add);
                }

                ilGen.Emit(OpCodes.Ldind_I2);
                ilGen.BranchTrue(labNotEmpty);
            }

            if (size >= 1)
            {
                ilGen.LoadLocalAddress(local);
                ilGen.Emit(OpCodes.Ldind_I1);
                ilGen.BranchTrue(labNotEmpty);
            }

            ilGen.Branch(label);

            ilGen.MarkLabel(labNotEmpty);
        }