Esempio n. 1
0
        /// <summary>
        /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will return this expression.
        /// </summary>
        /// <param name="breakLabel">The <see cref="LoopCSharpStatement.BreakLabel" /> property of the result.</param>
        /// <param name="continueLabel">The <see cref="LoopCSharpStatement.ContinueLabel" /> property of the result.</param>
        /// <param name="test">The <see cref="ConditionalLoopCSharpStatement.Test" /> property of the result.</param>
        /// <param name="body">The <see cref="LoopCSharpStatement.Body" /> property of the result.</param>
        /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
        public WhileCSharpStatement Update(LabelTarget breakLabel, LabelTarget continueLabel, Expression test, Expression body)
        {
            if (breakLabel == this.BreakLabel && continueLabel == this.ContinueLabel && test == this.Test && body == this.Body)
            {
                return(this);
            }

            return(CSharpExpression.While(test, body, breakLabel, continueLabel));
        }
        /// <summary>
        /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will return this expression.
        /// </summary>
        /// <param name="breakLabel">The <see cref="LoopCSharpStatement.BreakLabel" /> property of the result.</param>
        /// <param name="continueLabel">The <see cref="LoopCSharpStatement.ContinueLabel" /> property of the result.</param>
        /// <param name="test">The <see cref="ConditionalLoopCSharpStatement.Test" /> property of the result.</param>
        /// <param name="body">The <see cref="LoopCSharpStatement.Body" /> property of the result.</param>
        /// <param name="locals">The <see cref="ConditionalLoopCSharpStatement.Locals" /> property of the result.</param>
        /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
        public WhileCSharpStatement Update(LabelTarget breakLabel, LabelTarget continueLabel, Expression test, Expression body, IEnumerable <ParameterExpression> locals)
        {
            if (breakLabel == BreakLabel && continueLabel == ContinueLabel && test == Test && body == Body && SameElements(ref locals, Locals))
            {
                return(this);
            }

            return(CSharpExpression.While(test, body, breakLabel, continueLabel, locals));
        }
Esempio n. 3
0
            protected override Expression ReduceCore()
            {
                var getEnumerator      = Expression.Call(Collection, _getEnumerator);
                var enumeratorType     = getEnumerator.Type;
                var enumeratorVariable = Expression.Parameter(enumeratorType, "__enumerator");

                var moveNext = Expression.Call(enumeratorVariable, _moveNext);
                var current  = (Expression)Expression.Property(enumeratorVariable, _current);

                if (Conversion != null)
                {
                    current = Expression.Invoke(Conversion, current);
                }

                var cleanup = (Expression)Expression.Empty();

                if (typeof(IDisposable).IsAssignableFrom(enumeratorType))
                {
                    if (enumeratorType.IsValueType)
                    {
                        // NB: C# spec section 8.8.4 specifies a case for E being a nullable value type;
                        //     however, it seems this case can't occur because the check for the foreach
                        //     pattern would fail if E is a nullable value type (no Current property).
                        //     Double-check this.
                        Debug.Assert(!enumeratorType.IsNullableType());

                        var dispose = enumeratorType.FindDisposeMethod();
                        cleanup = Expression.Call(enumeratorVariable, dispose);
                    }
                    else
                    {
                        var dispose = enumeratorType.FindDisposeMethod();
                        cleanup =
                            Expression.IfThen(
                                Expression.ReferenceNotEqual(enumeratorVariable, Expression.Constant(null, typeof(IDisposable))),
                                Expression.Call(enumeratorVariable, dispose)
                                );
                    }
                }
                else if (!enumeratorType.IsSealed)
                {
                    var d = Expression.Parameter(typeof(IDisposable), "__disposable");
                    cleanup =
                        Expression.Block(
                            new[] { d },
                            Expression.Assign(d, Expression.TypeAs(enumeratorVariable, typeof(IDisposable))),
                            Expression.IfThen(
                                Expression.ReferenceNotEqual(d, Expression.Constant(null, typeof(IDisposable))),
                                Expression.Call(d, typeof(IDisposable).GetMethod("Dispose"))
                                )
                            );
                }

                var res =
                    Expression.Block(
                        new[] { enumeratorVariable },
                        Expression.Assign(enumeratorVariable, getEnumerator),
                        Expression.TryFinally(
                            CSharpExpression.While(
                                moveNext,
                                // NB: This is using C# 5.0 scoping rules for the loop variable.
                                Expression.Block(
                                    new[] { Variable },
                                    Expression.Assign(Variable, current),
                                    Body
                                    ),
                                BreakLabel,
                                ContinueLabel
                                ),
                            cleanup
                            )
                        );

                return(res);
            }