InvalidCompoundAssignmentWithOperands() статический приватный Метод

ArgumentException with message like "Compound assignment operation '{0}' is not supported for operands of type '{1}' and '{2}'."
static private InvalidCompoundAssignmentWithOperands ( object p0, object p1, object p2 ) : Exception
p0 object
p1 object
p2 object
Результат System.Exception
        private static void ValidateCustomBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right, ref MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            var leftType  = left.Type;
            var rightType = right.Type;

            if (leftConversion != null)
            {
                leftType = ValidateConversion(binaryType, leftType, leftConversion);
            }

            // NB: Just leverage LINQ to do the dirty work to check everything. Note that this assumes that the
            //     left conversion performed widening if that's required for the underlying operation. However,
            //     the use of FunctionalOp below will widen the right operand to match the left operand's type,
            //     which is what we do during Reduce as well (see remarks in FunctionalOp). This could produce
            //     mysterious error messages. (TODO: Review what's most appropriate here.)
            //
            // NB: We can't have it check the final conversion, because it doesn't allow these without the use of
            //     a custom method, so we check that ourselves further down.

            var leftDummy    = Expression.Parameter(leftType, "__left");
            var rightDummy   = Expression.Parameter(rightType, "__right");
            var functionalOp = FunctionalOp(binaryType, leftDummy, rightDummy, method);

            if (method == null)
            {
                method = functionalOp.Method;
            }

            var resultType = functionalOp.Type;

            if (finalConversion != null)
            {
                resultType = ValidateConversion(binaryType, resultType, finalConversion);
            }

            if (!TypeUtils.AreEquivalent(resultType, left.Type))
            {
                throw Error.InvalidCompoundAssignmentWithOperands(binaryType, left.Type, right.Type);
            }
        }
        private static AssignBinaryCSharpExpression MakeBinaryAssignCore(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression finalConversion, LambdaExpression leftConversion)
        {
            Helpers.RequiresCanWrite(left, nameof(left));
            RequiresCanRead(right, nameof(right));

            // NB: We could return a BinaryExpression in case the lhs is not one of our index nodes, but it'd change
            //     the return type to Expression which isn't nice to consume. Also, the Update method would either
            //     have to change to return Expression or we should have an AssignBinary node to hold a Binary node
            //     underneath it. This said, a specialized layout for the case where the custom node trivially wraps
            //     a LINQ node could be useful (just make Left virtual).

            if (binaryType != CSharpExpressionType.Assign)
            {
                var leftType  = left.Type;
                var rightType = right.Type;

                if (leftType == typeof(string))
                {
                    if (method == null)
                    {
                        if (binaryType == CSharpExpressionType.AddAssign || binaryType == CSharpExpressionType.AddAssignChecked)
                        {
                            if (rightType == typeof(string))
                            {
                                method = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) });
                            }
                            else
                            {
                                method = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(object) });

                                if (!TypeUtils1.AreReferenceAssignable(typeof(object), rightType))
                                {
                                    // DESIGN: Should our factory do this our just reject the input?
                                    right = Expression.Convert(right, typeof(object));
                                }
                            }
                        }
                        else
                        {
                            throw Error.InvalidCompoundAssignment(binaryType, typeof(string));
                        }
                    }
                }
                else if (typeof(MulticastDelegate).IsAssignableFrom(leftType))
                {
                    if (leftType == typeof(MulticastDelegate))
                    {
                        throw Error.InvalidCompoundAssignmentWithOperands(binaryType, leftType, rightType);
                    }

                    // NB: This checks for assignment with variance checks in mind, e.g.
                    //
                    //       Action<string> s = ...;
                    //       Action<object> o = ...;
                    //       s += o;

                    if (!TypeUtils1.AreReferenceAssignable(leftType, rightType))
                    {
                        throw Error.InvalidCompoundAssignmentWithOperands(binaryType, leftType, rightType);
                    }

                    if (method == null)
                    {
                        if (binaryType == CSharpExpressionType.AddAssign || binaryType == CSharpExpressionType.AddAssignChecked)
                        {
                            method = typeof(Delegate).GetMethod(nameof(Delegate.Combine), new[] { typeof(Delegate), typeof(Delegate) });
                        }
                        else if (binaryType == CSharpExpressionType.SubtractAssign || binaryType == CSharpExpressionType.SubtractAssignChecked)
                        {
                            method = typeof(Delegate).GetMethod(nameof(Delegate.Remove), new[] { typeof(Delegate), typeof(Delegate) });
                        }
                        else
                        {
                            throw Error.InvalidCompoundAssignment(binaryType, leftType);
                        }

                        if (finalConversion == null)
                        {
                            var resultParameter = Expression.Parameter(typeof(Delegate), "__result");
                            var convertResult   = Expression.Convert(resultParameter, leftType);
                            finalConversion = Expression.Lambda(convertResult, resultParameter);
                        }
                    }
                }
                else if (IsCSharpSpecificCompoundNumeric(leftType))
                {
                    // NB: If any of these are passed, we'll assume the types all line up. The call to
                    //     the ValidateCustomBinaryAssign method below will check that's indeed the case.

                    if (method == null && leftConversion == null && finalConversion == null)
                    {
                        var isChecked = IsCheckedBinary(binaryType);

                        var isNullabeLeftType = leftType.IsNullableType();
                        var nonNullLeftType   = leftType.GetNonNullableType();
                        var intermediateType  = nonNullLeftType.IsEnum ? nonNullLeftType.GetEnumUnderlyingType() : typeof(int);

                        var leftParameter = Expression.Parameter(leftType, "__left");
                        var convertType   = isNullabeLeftType ? typeof(Nullable <>).MakeGenericType(intermediateType) : intermediateType;
                        var convertLeft   = isChecked ? Expression.ConvertChecked(leftParameter, convertType) : Expression.Convert(leftParameter, convertType);
                        leftConversion = Expression.Lambda(convertLeft, leftParameter);

                        var resultParameter = Expression.Parameter(convertType, "__result");
                        var convertResult   = isChecked ? Expression.ConvertChecked(resultParameter, leftType) : Expression.Convert(resultParameter, leftType);
                        finalConversion = Expression.Lambda(convertResult, resultParameter);

                        if (rightType != convertType)
                        {
                            // DESIGN: Should our factory do this or just reject the input? On the one hand,
                            //         C# allows e.g. byte += byte, so if this is a C#-specific API it may be
                            //         reasonable for the user to expect such a tree can be built. On the
                            //         other hand, it's very unlike the expression tree API to insert nodes
                            //         on behalf of the user in the factories. Note that Roslyn often models
                            //         conversions as properties on a node using a `Conversion` objects
                            //         which would be handy to keep the shape from the tree isomorphic to the
                            //         bound nodes in the compiler. Note though that the RHS of a compound
                            //         assignment doesn't have such a conversion and the compiler will insert
                            //         a convert node in this case, so this is really just a convenience in
                            //         our factory method to mimic that behavior.
                            right = Expression.Convert(right, convertType);
                        }
                    }
                }
            }

            return(AssignBinaryCSharpExpression.Make(binaryType, left, right, method, leftConversion, finalConversion));
        }