internal override Expression GetExpression()
            {
                if (_instance == null)
                {
                    return(Expression.Equal
                           (
                               Expression.Convert(_expression, typeof(object)),
                               AstUtils.Null
                           ));
                }

                var temp = Expression.Parameter(typeof(object), null);

                return(Expression.Block
                       (
                           ReadOnlyCollectionEx.Create(temp),
                           ReadOnlyCollectionEx.Create <Expression>
                           (
#if ENABLEDYNAMICPROGRAMMING
                               Expression.Assign(
                                   temp,
                                   Expression.Property(
                                       Expression.Constant(new WeakReference(_instance)),
                                       typeof(WeakReference).GetProperty("Target")
                                       )
                                   ),
#else
                               Expression.Assign
                               (
                                   temp,
                                   Expression.Constant(_instance, typeof(object))
                               ),
#endif
                               Expression.AndAlso
                               (
                                   //check that WeakReference was not collected.
                                   Expression.NotEqual(temp, AstUtils.Null),
                                   Expression.Equal
                                   (
                                       Expression.Convert(_expression, typeof(object)),
                                       temp
                                   )
                               )
                           )
                       ));
            }
Exemple #2
0
        public static ReadOnlyCollectionEx <T> ToReadOnlyCollection <T>(this IEnumerable <T> enumerable)
        {
            switch (enumerable)
            {
            case null:
                return(EmptyCollection <T> .Instance);

            case ReadOnlyCollectionEx <T> arrayReadOnlyCollection:
                return(arrayReadOnlyCollection);

            default:
            {
                var array = AsArrayInternal(enumerable);
                return(array.Length == 0 ? EmptyCollection <T> .Instance : ReadOnlyCollectionEx.Create(array));
            }
            }
        }
Exemple #3
0
            protected internal override Expression VisitRuntimeVariables(RuntimeVariablesExpression node)
            {
                var count   = node.Variables.Count;
                var boxes   = new List <IStrongBox>();
                var vars    = new List <ParameterExpression>();
                var indexes = new int[count];

                for (var i = 0; i < indexes.Length; i++)
                {
                    var box = GetBox(node.Variables[i]);
                    if (box == null)
                    {
                        indexes[i] = vars.Count;
                        vars.Add(node.Variables[i]);
                    }
                    else
                    {
                        indexes[i] = -1 - boxes.Count;
                        boxes.Add(box);
                    }
                }

                // No variables were rewritten. Just return the original node.
                if (boxes.Count == 0)
                {
                    return(node);
                }

                var boxesConst = Expression.Constant(new RuntimeOps.RuntimeVariables(boxes.ToArray()), typeof(IRuntimeVariables));

                // All of them were rewritten. Just return the array as a constant
                if (vars.Count == 0)
                {
                    return(boxesConst);
                }

                // Otherwise, we need to return an object that merges them.
                return(Expression.Invoke
                       (
                           Expression.Constant(new Func <IRuntimeVariables, IRuntimeVariables, int[], IRuntimeVariables>(MergeRuntimeVariables)),
                           Expression.RuntimeVariables(ReadOnlyCollectionEx.Create(vars.ToArray())),
                           boxesConst,
                           Expression.Constant(indexes)
                       ));
            }
        /// <summary>
        ///     Creates a <see cref="ListInitExpression" /> that uses a specified method to add elements to a collection.
        /// </summary>
        /// <param name="newExpression">
        ///     A <see cref="NewExpression" /> to set the <see cref="ListInitExpression.NewExpression" />
        ///     property equal to.
        /// </param>
        /// <param name="addMethod">
        ///     A <see cref="MethodInfo" /> that represents an instance method named "Add" (case insensitive),
        ///     that adds an element to a collection.
        /// </param>
        /// <param name="initializers">
        ///     An <see cref="IEnumerable{T}" /> that contains <see cref="Expression" /> objects to use to
        ///     populate the Initializers collection.
        /// </param>
        /// <returns>
        ///     A <see cref="ListInitExpression" /> that has the <see cref="NodeType" /> property equal to
        ///     <see cref="ExpressionType.ListInit" /> and the <see cref="ListInitExpression.NewExpression" /> property set to the
        ///     specified value.
        /// </returns>
        public static ListInitExpression ListInit(NewExpression newExpression, MethodInfo addMethod, IEnumerable <Expression> initializers)
        {
            if (addMethod == null)
            {
                return(ListInit(newExpression, initializers));
            }

            ContractUtils.RequiresNotNull(newExpression, nameof(newExpression));
            ContractUtils.RequiresNotNull(initializers, nameof(initializers));

            var initializerList = initializers.ToReadOnlyCollection();
            var initList        = new ElementInit[initializerList.Count];

            for (var i = 0; i < initializerList.Count; i++)
            {
                initList[i] = ElementInit(addMethod, initializerList[i]);
            }

            return(ListInit(newExpression, ReadOnlyCollectionEx.Create(initList)));
        }
        public static ReadOnlyCollectionEx <T> ToReadOnlyCollection <T>(this IEnumerable <T> enumerable)
        {
            switch (enumerable)
            {
            case null:
                return(EmptyCollection <T> .Instance);

            case ReadOnlyCollectionEx <T> arrayReadOnlyCollection:
                return(arrayReadOnlyCollection);

            default:
            {
                var array = AsArrayInternal(enumerable);
#pragma warning disable CA1062 // Validate arguments of public methods
                return(array.Length == 0 ? EmptyCollection <T> .Instance : ReadOnlyCollectionEx.Create(array));

#pragma warning restore CA1062 // Validate arguments of public methods
            }
            }
        }
Exemple #6
0
        private static NewArrayExpression NewArrayInitExtracted(Type type, IEnumerable <Expression> initializers, string initializersName)
        {
            var initializerList = initializers.ToReadOnlyCollection();

            Expression[]? newList = null;
            for (int i = 0, n = initializerList.Count; i < n; i++)
            {
                var expr = initializerList[i];
                ContractUtils.RequiresNotNull(expr, initializersName, i);
                ExpressionUtils.RequiresCanRead(expr, initializersName, i);

                if (!type.IsReferenceAssignableFromInternal(expr.Type))
                {
                    if (!TryQuote(type, ref expr))
                    {
                        throw new InvalidOperationException($"An expression of type '{expr.Type}' cannot be used to initialize an array of type '{type}'");
                    }

                    if (newList == null)
                    {
                        newList = new Expression[initializerList.Count];
                        for (var j = 0; j < i; j++)
                        {
                            newList[j] = initializerList[j];
                        }
                    }
                }

                if (newList != null)
                {
                    newList[i] = expr;
                }
            }

            if (newList != null)
            {
                initializerList = ReadOnlyCollectionEx.Create(newList);
            }

            return(NewArrayExpression.Make(ExpressionType.NewArrayInit, type.MakeArrayType(), initializerList));
        }
Exemple #7
0
        private Result RewriteNewArrayExpression(Expression expr, Stack stack)
        {
            var node = (NewArrayExpression)expr;

            if (node.NodeType == ExpressionType.NewArrayInit)
            {
                // In a case of array construction with element initialization
                // the element expressions are never emitted on an empty stack because
                // the array reference and the index are on the stack.
                stack = Stack.NonEmpty;
            }

            var cr = new ChildRewriter(this, stack, node.Expressions.Count);

            cr.Add(node.Expressions);

            if (cr.Rewrite)
            {
                expr = NewArrayExpression.Make(node.NodeType, node.Type, ReadOnlyCollectionEx.Create(cr[0, -1]));
            }

            return(cr.Finish(expr));
        }
Exemple #8
0
 internal RuntimeVariablesExpression(ParameterExpression[] variables)
 {
     _variables = variables;
     _variablesAsReadOnlyCollection = ReadOnlyCollectionEx.Create(_variables);
 }
Exemple #9
0
 internal ElementInit(MethodInfo addMethod, Expression[] arguments)
 {
     AddMethod = addMethod;
     _argumentsAsReadOnlyCollection = ReadOnlyCollectionEx.Create(arguments);
 }
Exemple #10
0
            private DynamicMetaObject BuildCallMethodWithResult <TBinder>(MethodInfo method, TBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Func <MetaDynamic, TBinder, DynamicMetaObject?, DynamicMetaObject>?fallbackInvoke)
                where TBinder : DynamicMetaObjectBinder
            {
                if (!IsOverridden(method))
                {
                    return(fallbackResult);
                }

                // Build a new expression like:
                #pragma warning disable S125 // Sections of code should not be commented out
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
                // }
                #pragma warning restore S125 // Sections of code should not be commented out

                var result        = Expression.Parameter(typeof(object), null);
                var callArgs      = method != CachedReflectionInfo.DynamicObjectTryBinaryOperation ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
                var callArgsValue = GetConvertedArgs(args);

                var resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty);

                // Need to add a conversion if calling TryConvert
                if (binder.ReturnType != typeof(object))
                {
                    Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                    var convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType);
                    // will always be a cast or unbox
                    Debug.Assert(convert.Method == null);

                    // Prepare a good exception message in case the convert will fail
                    var convertFailed = $"The result type '{{0}}' of the dynamic binding produced by the object with type '{Value!.GetType()}' for the binder '{binder.GetType()}' is not compatible with the result type '{binder.ReturnType}' expected by the call site.";

                    // If the return type can not be assigned null then just check for type assignability otherwise allow null.
                    var condition = binder.ReturnType.IsValueType && Nullable.GetUnderlyingType(binder.ReturnType) == null
                        ? (Expression)Expression.TypeIs(resultMetaObject.Expression, binder.ReturnType)
                        : Expression.OrElse
                                    (
                        Expression.Equal(resultMetaObject.Expression, AstUtils.Null),
                        Expression.TypeIs(resultMetaObject.Expression, binder.ReturnType)
                                    );

                    Expression checkedConvert = Expression.Condition
                                                (
                        condition,
                        convert,
                        Expression.Throw
                        (
                            Expression.New
                            (
                                CachedReflectionInfo.InvalidCastExceptionCtorString,
                                ReadOnlyCollectionEx.Create <Expression>
                                (
                                    Expression.Call
                                    (
                                        CachedReflectionInfo.StringFormatStringObjectArray,
                                        Expression.Constant(convertFailed),
                                        Expression.NewArrayInit
                                        (
                                            typeof(object),
                                            ReadOnlyCollectionEx.Create <Expression>
                                            (
                                                Expression.Condition
                                                (
                                                    Expression.Equal(resultMetaObject.Expression, AstUtils.Null),
                                                    Expression.Constant("null"),
                                                    Expression.Call
                                                    (
                                                        resultMetaObject.Expression,
                                                        CachedReflectionInfo.ObjectGetType
                                                    ),
                                                    typeof(object)
                                                )
                                            )
                                        )
                                    )
                                )
                            ),
                            binder.ReturnType
                        ),
                        binder.ReturnType
                                                );

                    resultMetaObject = new DynamicMetaObject(checkedConvert, resultMetaObject.Restrictions);
                }

                if (fallbackInvoke != null)
                {
                    resultMetaObject = fallbackInvoke(this, binder, resultMetaObject);
                }

                return(new DynamicMetaObject
                       (
                           Expression.Block
                           (
                               ReadOnlyCollectionEx.Create(result, callArgs),
                               ReadOnlyCollectionEx.Create <Expression>
                               (
                                   method != CachedReflectionInfo.DynamicObjectTryBinaryOperation ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
                                   Expression.Condition
                                   (
                                       Expression.Call
                                       (
                                           GetLimitedSelf(),
                                           method,
                                           BuildCallArgs
                                           (
                                               binder,
                                               args,
                                               callArgs,
                                               result
                                           )
                                       ),
                                       Expression.Block
                                       (
                                           method != CachedReflectionInfo.DynamicObjectTryBinaryOperation ? ReferenceArgAssign(callArgs, args) : AstUtils.Empty,
                                           resultMetaObject.Expression
                                       ),
                                       fallbackResult.Expression,
                                       binder.ReturnType
                                   )
                               )
                           ),
                           GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions)
                       ));
            }
Exemple #11
0
 protected ProgressiveList(Progressor <T> progressor, IList <T> cache, IEqualityComparer <T> comparer)
     : base(progressor, cache, comparer)
 {
     _cache = cache;
     Cache  = new ReadOnlyCollectionEx <T>(_cache);
 }
 internal ScopeN(ParameterExpression[] variables, Expression[] body)
     : base(variables)
 {
     _body = body;
     _bodyAsReadOnlyCollection = ReadOnlyCollectionEx.Create(_body);
 }
Exemple #13
0
 internal SwitchCase(Expression body, Expression[] testValues)
 {
     Body        = body;
     _testValues = testValues;
     _textValuesAsReadOnlyCollection = ReadOnlyCollectionEx.Create(_testValues);
 }
Exemple #14
0
 internal MemberInitExpression(NewExpression newExpression, MemberBinding[] bindings)
 {
     NewExpression = newExpression;
     _bindings     = bindings;
     _bindingsAsReadOnlyCollection = ReadOnlyCollectionEx.Create(_bindings);
 }
Exemple #15
0
        private bool TryEmitHashtableSwitch(SwitchExpression node, CompilationFlags flags)
        {
            // If we have a comparison other than string equality, bail
            if (node.Comparison != CachedReflectionInfo.StringOpEqualityStringString && node.Comparison != CachedReflectionInfo.StringEqualsStringString)
            {
                return(false);
            }

            // All test values must be constant.
            var tests = 0;

            foreach (var c in node.Cases)
            {
                foreach (var t in c.TestValues)
                {
                    if (!(t is ConstantExpression))
                    {
                        return(false);
                    }

                    tests++;
                }
            }

            // Must have >= 7 labels for it to be worth it.
            if (tests < 7)
            {
                return(false);
            }

            // If we're in a DynamicMethod, we could just build the dictionary
            // immediately. But that would cause the two code paths to be more
            // different than they really need to be.
            var initializers = new List <ElementInit>(tests);
            var cases        = new ArrayBuilder <SwitchCase>(node.Cases.Count);

            var nullCase = -1;
            var add      = CachedReflectionInfo.DictionaryOfStringInt32AddStringInt32;

            for (int i = 0, n = node.Cases.Count; i < n; i++)
            {
                foreach (var expression in node.Cases[i].TestValues)
                {
                    var t = (ConstantExpression)expression;
                    if (t.Value != null)
                    {
                        initializers.Add(Expression.ElementInit(add, ReadOnlyCollectionEx.Create <Expression>(t, Utils.Constant(i))));
                    }
                    else
                    {
                        nullCase = i;
                    }
                }

                cases.UncheckedAdd(Expression.SwitchCase(node.Cases[i].Body, ReadOnlyCollectionEx.Create <Expression>(Utils.Constant(i))));
            }

            // Create the field to hold the lazily initialized dictionary
            var dictField = CreateLazyInitializedField <Dictionary <string, int> >("dictionarySwitch");

            // If we happen to initialize it twice (multithreaded case), it's
            // not the end of the world. The C# compiler does better here by
            // emitting a volatile access to the field.
            Expression dictInit = Expression.Condition
                                  (
                Expression.Equal(dictField, Expression.Constant(null, dictField.Type)),
                Expression.Assign
                (
                    dictField,
                    Expression.ListInit
                    (
                        Expression.New
                        (
                            CachedReflectionInfo.DictionaryOfStringInt32CtorInt32,
                            ReadOnlyCollectionEx.Create <Expression>
                            (
                                Utils.Constant(initializers.Count)
                            )
                        ),
                        initializers
                    )
                ),
                dictField
                                  );

            //
            // Create a tree like:
            //
            // switchValue = switchValueExpression;
            // if (switchValue == null) {
            //     switchIndex = nullCase;
            // } else {
            //     if (_dictField == null) {
            //         _dictField = new Dictionary<string, int>(count) { { ... }, ... };
            //     }
            //     if (!_dictField.TryGetValue(switchValue, out switchIndex)) {
            //         switchIndex = -1;
            //     }
            // }
            // switch (switchIndex) {
            //     case 0: ...
            //     case 1: ...
            //     ...
            //     default:
            // }
            //
            var switchValue = Expression.Variable(typeof(string), "switchValue");
            var switchIndex = Expression.Variable(typeof(int), "switchIndex");
            var reduced     = Expression.Block
                              (
                ReadOnlyCollectionEx.Create(switchIndex, switchValue),
                ReadOnlyCollectionEx.Create <Expression>
                (
                    Expression.Assign(switchValue, node.SwitchValue),
                    Expression.IfThenElse
                    (
                        Expression.Equal(switchValue, Expression.Constant(null, typeof(string))),
                        Expression.Assign(switchIndex, Utils.Constant(nullCase)),
                        Expression.IfThenElse
                        (
                            Expression.Call(dictInit, "TryGetValue", null, switchValue, switchIndex),
                            Utils.Empty,
                            Expression.Assign(switchIndex, Utils.Constant(-1))
                        )
                    ),
                    Expression.Switch(node.Type, switchIndex, node.DefaultBody, null, cases.ToArray())
                )
                              );

            EmitExpression(reduced, flags);
            return(true);
        }
Exemple #16
0
 internal NewArrayExpression(Type type, Expression[] expressions)
 {
     _expressions = expressions;
     Type         = type;
     _expressionsAsReadOnlyCollection = ReadOnlyCollectionEx.Create(_expressions);
 }
Exemple #17
0
        private Result RewriteListInitExpression(Expression expr, Stack stack)
        {
            var node = (ListInitExpression)expr;

            // Constructor runs on initial stack.
            var newResult    = RewriteExpression(node.NewExpression, stack);
            var rewrittenNew = newResult.Node;
            var action       = newResult.Action;

            var initializers = node.Initializers;
            var count        = initializers.Count;

            var cloneCrs = new ChildRewriter[count];

            for (var i = 0; i < count; i++)
            {
                var init = initializers[i];

                // Initializers all run on non-empty stack (the list instance is on it).
                var cr = new ChildRewriter(this, Stack.NonEmpty, init.Arguments.Count);
                cr.Add(init.Arguments);

                action     |= cr.Action;
                cloneCrs[i] = cr;
            }

            switch (action)
            {
            case RewriteAction.None:
                break;

            case RewriteAction.Copy:
                var newInitializer = new ElementInit[count];
                for (var i = 0; i < count; i++)
                {
                    var cr = cloneCrs[i];
                    if (cr.Action == RewriteAction.None)
                    {
                        newInitializer[i] = initializers[i];
                    }
                    else
                    {
                        newInitializer[i] = new ElementInit(initializers[i].AddMethod, cr[0, -1]);
                    }
                }

                expr = new ListInitExpression((NewExpression)rewrittenNew, ReadOnlyCollectionEx.Create(newInitializer));
                break;

            case RewriteAction.SpillStack:
                var isRefNew = IsRefInstance(node.NewExpression);

                var comma   = new ArrayBuilder <Expression>(count + 2 + (isRefNew ? 1 : 0));
                var tempNew = MakeTemp(rewrittenNew.Type);
                comma.UncheckedAdd(new AssignBinaryExpression(tempNew, rewrittenNew));

                var refTempNew = tempNew;
                if (isRefNew)
                {
                    refTempNew = MakeTemp(tempNew.Type.MakeByRefType());
                    comma.UncheckedAdd(new ByRefAssignBinaryExpression(refTempNew, tempNew));
                }

                for (var i = 0; i < count; i++)
                {
                    var cr  = cloneCrs[i];
                    var add = cr.Finish(new InstanceMethodCallExpressionN(initializers[i].AddMethod, refTempNew, cr[0, -1]));
                    comma.UncheckedAdd(add.Node);
                }

                comma.UncheckedAdd(tempNew);

                expr = MakeBlock(comma);
                break;

            default:
                throw ContractUtils.Unreachable;
            }

            return(new Result(action, expr));
        }
Exemple #18
0
            private DynamicMetaObject CallMethodReturnLast <TBinder>(MethodInfo method, TBinder binder, Expression[] args, Expression value, Func <MetaDynamic, TBinder, DynamicMetaObject?, DynamicMetaObject> fallback)
                where TBinder : DynamicMetaObjectBinder
            {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                var fallbackResult = fallback(this, binder, null);

                // Build a new expression like:
                #pragma warning disable S125 // Sections of code should not be commented out
                // {
                //   object result;
                //   TrySetMember(payload, result = value) ? result : fallbackResult
                // }
                #pragma warning restore S125 // Sections of code should not be commented out

                var result        = Expression.Parameter(typeof(object), null);
                var callArgs      = Expression.Parameter(typeof(object[]), null);
                var callArgsValue = GetConvertedArgs(args);

                var callDynamic = new DynamicMetaObject
                                  (
                    Expression.Block
                    (
                        ReadOnlyCollectionEx.Create(result, callArgs),
                        ReadOnlyCollectionEx.Create <Expression>
                        (
                            Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)),
                            Expression.Condition
                            (
                                Expression.Call
                                (
                                    GetLimitedSelf(),
                                    method,
                                    BuildCallArgs
                                    (
                                        binder,
                                        args,
                                        callArgs,
                                        Expression.Assign(result, Expression.Convert(value, typeof(object)))
                                    )
                                ),
                                Expression.Block
                                (
                                    ReferenceArgAssign(callArgs, args),
                                    result
                                ),
                                fallbackResult.Expression,
                                typeof(object)
                            )
                        )
                    ),
                    GetRestrictions().Merge(fallbackResult.Restrictions)
                                  );

                //
                // Now, call fallback again using our new MO as the error
                // When we do this, one of two things can happen:
                //   1. Binding will succeed, and it will ignore our call to
                //      the dynamic method, OR
                //   2. Binding will fail, and it will use the MO we created
                //      above.
                //
                return(fallback(this, binder, callDynamic));
            }
Exemple #19
0
 public InvocationExpressionN(Expression lambda, Expression[] arguments, Type returnType)
     : base(lambda, returnType)
 {
     _arguments           = arguments;
     _argumentsAsReadOnly = ReadOnlyCollectionEx.Create(_arguments);
 }
Exemple #20
0
        private static void ValidateNewArgs(ConstructorInfo constructor, ref Expression[] arguments, ref ReadOnlyCollectionEx <MemberInfo> members)
        {
            ParameterInfo[] pis = constructor.GetParameters();
            if (pis.Length > 0)
            {
                if (arguments.Length != pis.Length)
                {
                    throw new ArgumentException("Incorrect number of arguments for constructor");
                }

                if (arguments.Length != members.Count)
                {
                    throw new ArgumentException("Incorrect number of arguments for the given members ");
                }

                Expression[]? newArguments = null;
                MemberInfo[]? newMembers   = null;
                for (int i = 0, n = arguments.Length; i < n; i++)
                {
                    var arg = arguments[i];
                    ContractUtils.RequiresNotNull(arg, nameof(arguments), i);
                    ExpressionUtils.RequiresCanRead(arg, nameof(arguments), i);
                    var member = members[i];
                    ContractUtils.RequiresNotNull(member, nameof(members), i);
                    if (!TypeUtils.AreEquivalent(member.DeclaringType, constructor.DeclaringType))
                    {
                        throw new ArgumentException($" The member '{member.Name}' is not declared on type '{constructor.DeclaringType?.Name}' being created", i >= 0 ? $"{nameof(members)}[{i}]" : nameof(members));
                    }

                    ValidateAnonymousTypeMember(ref member, out var memberType, nameof(members), i);
                    if (!memberType.IsReferenceAssignableFromInternal(arg.Type) && !TryQuote(memberType, ref arg))
                    {
                        throw new ArgumentException($" Argument type '{arg.Type}' does not match the corresponding member type '{memberType}'", i >= 0 ? $"{nameof(arguments)}[{i}]" : nameof(arguments));
                    }

                    var pi    = pis[i];
                    var pType = pi.ParameterType;
                    if (pType.IsByRef)
                    {
                        pType = pType.GetElementType();
                    }

                    if (!pType.IsReferenceAssignableFromInternal(arg.Type) && !TryQuote(pType, ref arg))
                    {
                        throw new ArgumentException($"Expression of type '{arg.Type}' cannot be used for constructor parameter of type '{pType}'", i >= 0 ? $"{nameof(arguments)}[{i}]" : nameof(arguments));
                    }

                    if (newArguments == null && arg != arguments[i])
                    {
                        newArguments = new Expression[arguments.Length];
                        for (var j = 0; j < i; j++)
                        {
                            newArguments[j] = arguments[j];
                        }
                    }

                    if (newArguments != null)
                    {
                        newArguments[i] = arg;
                    }

                    if (newMembers == null && member != members[i])
                    {
                        newMembers = new MemberInfo[members.Count];
                        for (var j = 0; j < i; j++)
                        {
                            newMembers[j] = members[j];
                        }
                    }

                    if (newMembers != null)
                    {
                        newMembers[i] = member;
                    }
                }

                if (newArguments != null)
                {
                    arguments = newArguments;
                }

                if (newMembers != null)
                {
                    members = ReadOnlyCollectionEx.Create(newMembers);
                }
            }
            else if (arguments?.Length > 0)
            {
                throw new ArgumentException("Incorrect number of arguments for constructor");
            }
            else if (members?.Count > 0)
            {
                throw new ArgumentException("Incorrect number of members for constructor");
            }
        }