1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
21 namespace Microsoft.Scripting.Ast {
23 namespace System.Linq.Expressions {
27 /// Represents a catch statement in a try block.
28 /// This must have the same return type (i.e., the type of <see cref="P:CatchBlock.Body"/>) as the try block it is associated with.
30 [DebuggerTypeProxy(typeof(Expression.CatchBlockProxy))]
31 public sealed class CatchBlock {
32 private readonly Type _test;
33 private readonly ParameterExpression _var;
34 private readonly Expression _body;
35 private readonly Expression _filter;
37 internal CatchBlock(Type test, ParameterExpression variable, Expression body, Expression filter) {
45 /// Gets a reference to the <see cref="Exception"/> object caught by this handler.
47 public ParameterExpression Variable {
52 /// Gets the type of <see cref="Exception"/> this handler catches.
59 /// Gets the body of the catch block.
61 public Expression Body {
66 /// Gets the body of the <see cref="CatchBlock"/>'s filter.
68 public Expression Filter {
75 /// Returns a <see cref="String"/> that represents the current <see cref="Object"/>.
77 /// <returns>A <see cref="String"/> that represents the current <see cref="Object"/>. </returns>
78 public override string ToString() {
79 return ExpressionStringBuilder.CatchBlockToString(this);
83 /// Creates a new expression that is like this one, but using the
84 /// supplied children. If all of the children are the same, it will
85 /// return this expression.
87 /// <param name="variable">The <see cref="Variable" /> property of the result.</param>
88 /// <param name="filter">The <see cref="Filter" /> property of the result.</param>
89 /// <param name="body">The <see cref="Body" /> property of the result.</param>
90 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
91 public CatchBlock Update(ParameterExpression variable, Expression filter, Expression body) {
92 if (variable == Variable && filter == Filter && body == Body) {
95 return Expression.MakeCatchBlock(Test, variable, body, filter);
99 public partial class Expression {
101 /// Creates a <see cref="CatchBlock"/> representing a catch statement.
102 /// The <see cref="Type"/> of object to be caught can be specified but no reference to the object
103 /// will be available for use in the <see cref="CatchBlock"/>.
105 /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
106 /// <param name="body">The body of the catch statement.</param>
107 /// <returns>The created <see cref="CatchBlock"/>.</returns>
108 public static CatchBlock Catch(Type type, Expression body) {
109 return MakeCatchBlock(type, null, body, null);
113 /// Creates a <see cref="CatchBlock"/> representing a catch statement with a reference to the caught object for use in the handler body.
115 /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
116 /// <param name="body">The body of the catch statement.</param>
117 /// <returns>The created <see cref="CatchBlock"/>.</returns>
118 public static CatchBlock Catch(ParameterExpression variable, Expression body) {
119 ContractUtils.RequiresNotNull(variable, "variable");
120 return MakeCatchBlock(variable.Type, variable, body, null);
124 /// Creates a <see cref="CatchBlock"/> representing a catch statement with
125 /// an <see cref="Exception"/> filter but no reference to the caught <see cref="Exception"/> object.
127 /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
128 /// <param name="body">The body of the catch statement.</param>
129 /// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
130 /// <returns>The created <see cref="CatchBlock"/>.</returns>
131 public static CatchBlock Catch(Type type, Expression body, Expression filter) {
132 return MakeCatchBlock(type, null, body, filter);
136 /// Creates a <see cref="CatchBlock"/> representing a catch statement with
137 /// an <see cref="Exception"/> filter and a reference to the caught <see cref="Exception"/> object.
139 /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
140 /// <param name="body">The body of the catch statement.</param>
141 /// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
142 /// <returns>The created <see cref="CatchBlock"/>.</returns>
143 public static CatchBlock Catch(ParameterExpression variable, Expression body, Expression filter) {
144 ContractUtils.RequiresNotNull(variable, "variable");
145 return MakeCatchBlock(variable.Type, variable, body, filter);
149 /// Creates a <see cref="CatchBlock"/> representing a catch statement with the specified elements.
151 /// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
152 /// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
153 /// <param name="body">The body of the catch statement.</param>
154 /// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
155 /// <returns>The created <see cref="CatchBlock"/>.</returns>
156 /// <remarks><paramref name="type"/> must be non-null and match the type of <paramref name="variable"/> (if it is supplied).</remarks>
157 public static CatchBlock MakeCatchBlock(Type type, ParameterExpression variable, Expression body, Expression filter) {
158 ContractUtils.RequiresNotNull(type, "type");
159 ContractUtils.Requires(variable == null || TypeUtils.AreEquivalent(variable.Type, type), "variable");
160 if (variable != null && variable.IsByRef) {
161 throw Error.VariableMustNotBeByRef(variable, variable.Type);
163 RequiresCanRead(body, "body");
164 if (filter != null) {
165 RequiresCanRead(filter, "filter");
166 if (filter.Type != typeof(bool)) throw Error.ArgumentMustBeBoolean();
169 return new CatchBlock(type, variable, body, filter);