/// <summary>
        /// Cast a reference on the stack to the given reference type.
        ///
        /// If the cast is not legal, a CastClassException will be thrown at runtime.
        /// </summary>
        public Emit <DelegateType> CastClass(Type referenceType)
        {
            if (referenceType == null)
            {
                throw new ArgumentNullException("referenceType");
            }

            if (referenceType.IsValueType)
            {
                throw new ArgumentException("Can only cast to ReferenceTypes, found " + referenceType);
            }

            var  curIndex = IL.Index;
            bool elided   = false;

            VerificationCallback before =
                (stack, baseless) =>
            {
                // Can't reason about stack unless it's completely known
                if (baseless || elided)
                {
                    return;
                }

                var onStack = stack.First();

                if (onStack.All(a => ExtensionMethods.IsAssignableFrom(referenceType, a)))
                {
                    ElidableCasts.Add(curIndex);
                    elided = true;
                }
            };

            var newType = TypeOnStack.Get(referenceType);

            var transitions =
                new[]
            {
                new StackTransition(new [] { typeof(object) }, new [] { referenceType }, before: before)
            };

            UpdateState(OpCodes.Castclass, referenceType, Wrap(transitions, "CastClass"));

            return(this);
        }
Beispiel #2
0
        /// <summary>
        /// Pops a value from the stack and casts to the given type if possible pushing the result, otherwise pushes a null.
        ///
        /// This is analogous to C#'s `as` operator.
        /// </summary>
        public Emit <DelegateType> IsInstance(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            var  curIndex = IL.Index;
            bool elided   = false;

            VerificationCallback before =
                (stack, baseless) =>
            {
                // Can't reason about stack unless it's completely known
                if (baseless || elided)
                {
                    return;
                }

                var onStack = stack.First();

                if (onStack.All(a => ExtensionMethods.IsAssignableFrom(type, a)))
                {
                    ElidableCasts.Add(curIndex);
                    elided = true;
                }
            };

            var transitions =
                new[]
            {
                new StackTransition(new[] { typeof(WildcardType) }, new [] { type }, before)
            };

            UpdateState(OpCodes.Isinst, type, Wrap(transitions, "IsInstance"));

            return(this);
        }