示例#1
0
        public void ArrayAccess_ByRef_CSharpNodes_SystemIndex()
        {
            //
            // NB: Unlike the test case above, this works because we can reduce CSharpExpression variants of MethodCall, New, and Invoke
            //     while properly accounting for by-ref passing of ArrayAccess.
            //
            //     The corresponding changes to the Roslyn compiler account for by-ref passing of ArrayAccess nodes that involve an Index
            //     operand, causing calls to be made to CSharpExpression.* factories for Call, New, and Invoke.  E.g.
            //
            //        Interlocked.Exchange(ref xs[i])
            //
            //     where i is of type Index, becomes
            //
            //        CSharpExpression.Call(xchg, CSharpExpression.ArrayAccess(...))
            //
            //     rather than
            //
            //        Expression.Call(xchg, CSharpExpression.ArrayAccess(...))
            //
            //     This triggers custom reduction logic in the C# variants of Call, New, and Invoke nodes.
            //
            //     However, this does not fix the previous test case where one explicitly uses Expression.Call. For this to be fixed, we
            //     either need:
            //
            //       1. Guaranteed custom reduction at a higher node (e.g. lambda).
            //       2. Changes to ref semantics in System.Linq.Expressions, e.g. allowing to peek into a comma node.
            //       3. Changes to Reduce logic in System.Linq.Expressions, e.g. custom logic for lval reduciton versus rval reduction.
            //       4. Push down Index/Range support to IndexExpression and piggyback on its by-ref support.
            //

            var xs = Expression.Parameter(typeof(int[]));
            var i  = Expression.Parameter(typeof(Index));

            var inc = typeof(Interlocked).GetMethod(nameof(Interlocked.Increment), new[] { typeof(int).MakeByRefType() });

            MethodCallCSharpExpression mce = CSharpExpression.Call(inc, new Expression[] { CSharpExpression.ArrayAccess(xs, i) });

            var res = Expression.Lambda <Func <int[], Index, int> >(mce, xs, i);

            var f = res.Compile();

            var vals = new int[] { 41 };

            int val = f(vals, 0);

            Assert.AreEqual(42, val);
            Assert.AreEqual(42, vals[0]);
        }
示例#2
0
        public void ArrayAccess_ByRef_CSharpNodes_Int()
        {
            var xs = Expression.Parameter(typeof(int[]));
            var i  = Expression.Parameter(typeof(int));

            var inc = typeof(Interlocked).GetMethod(nameof(Interlocked.Increment), new[] { typeof(int).MakeByRefType() });

            MethodCallCSharpExpression mce = CSharpExpression.Call(inc, new Expression[] { CSharpExpression.ArrayAccess(xs, i) });

            var res = Expression.Lambda <Func <int[], int, int> >(mce, xs, i);

            var f = res.Compile();

            var vals = new int[] { 41 };

            int val = f(vals, 0);

            Assert.AreEqual(42, val);
            Assert.AreEqual(42, vals[0]);
        }
示例#3
0
            protected internal override Expression VisitMethodCall(MethodCallCSharpExpression node)
            {
                Visited = true;

                return(base.VisitMethodCall(node));
            }