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