GetUnderlyingType() public static method

public static GetUnderlyingType ( TypeSpec nullableType ) : TypeSpec
nullableType TypeSpec
return TypeSpec
Example #1
0
        protected override Expression DoResolve(ResolveContext rc)
        {
            base.DoResolve(rc);

            if (type != null)
            {
                type = NullableInfo.GetUnderlyingType(type);
            }

            return(this);
        }
Example #2
0
        public static Expression Create(Expression expr, TypeSpec type)
        {
            //
            // Avoid unwraping and wraping of the same type
            //
            if (expr is Unwrap unwrap && expr.Type == NullableInfo.GetUnderlyingType(type))
            {
                return(unwrap.Original);
            }

            return(new Wrap(expr, type));
        }
Example #3
0
        public override void Emit(EmitContext ec)
        {
            Label end_label = ec.DefineLabel();

            if (unwrap != null)
            {
                Label is_null_label = ec.DefineLabel();

                unwrap.EmitCheck(ec);
                ec.Emit(OpCodes.Brfalse, is_null_label);

                //
                // When both expressions are nullable the unwrap
                // is needed only for null check not for value uwrap
                //
                if (type.IsNullableType && TypeSpecComparer.IsEqual(NullableInfo.GetUnderlyingType(type), unwrap.Type))
                {
                    unwrap.Load(ec);
                }
                else
                {
                    left.Emit(ec);
                }

                ec.Emit(OpCodes.Br, end_label);

                ec.MarkLabel(is_null_label);
                right.Emit(ec);

                ec.MarkLabel(end_label);
                return;
            }

            //
            // Null check is done on original expression not after expression is converted to
            // result type. This is in most cases same but when user conversion is involved
            // we can end up in situation when use operator does the null handling which is
            // not what the operator is supposed to do
            //
            var op_expr = left as UserCast;

            if (op_expr != null)
            {
                op_expr.Source.Emit(ec);
                LocalTemporary temp;

                // TODO: More load kinds can be special cased
                if (!(op_expr.Source is VariableReference))
                {
                    temp = new LocalTemporary(op_expr.Source.Type);
                    temp.Store(ec);
                    temp.Emit(ec);
                    op_expr.Source = temp;
                }
                else
                {
                    temp = null;
                }

                var right_label = ec.DefineLabel();
                ec.Emit(OpCodes.Brfalse_S, right_label);
                left.Emit(ec);
                ec.Emit(OpCodes.Br, end_label);
                ec.MarkLabel(right_label);

                if (temp != null)
                {
                    temp.Release(ec);
                }
            }
            else
            {
                //
                // Common case where expression is not modified before null check and
                // we generate better/smaller code
                //
                left.Emit(ec);
                ec.Emit(OpCodes.Dup);

                // Only to make verifier happy
                if (left.Type.IsGenericParameter)
                {
                    ec.Emit(OpCodes.Box, left.Type);
                }

                ec.Emit(OpCodes.Brtrue, end_label);

                ec.Emit(OpCodes.Pop);
            }

            right.Emit(ec);

            ec.MarkLabel(end_label);
        }