/// <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); }
/// <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); }