Middle · Trace · Captured expression values versus parameters

Trace the effect of changing factor and explain the MemberAccess report.

Think through your answer before opening the explanation.

Runtime & concurrency

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Reflection;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

int factor = 3;
Expression<Func<int>> captured = () => factor * 2;
var read = captured.Compile(preferInterpretation: true);
Expression<Func<int, int>> parameterized = value => value * 2;
var apply = parameterized.Compile(preferInterpretation: true);
Console.WriteLine($"before:{read()}");
factor = 5;
Console.WriteLine($"after:{read()}");
Console.WriteLine($"input:{apply(3)}");
Console.WriteLine($"capture:{((BinaryExpression)captured.Body).Left.NodeType}");
Reveal answer and reasoning

The output is before:6, after:10, input:6, and capture:MemberAccess. The first captured invocation reads factor three and doubles it. Changing factor to five changes what the same captured computation reads next, so it returns ten. The parameterized tree receives three directly and therefore returns six without consulting factor. Its independent input is not changed by the ambient assignment.

The captured multiplication's left node accesses the closure member rather than a literal integer constant, explaining MemberAccess. The common wrong trace keeps after at six by assuming construction took a snapshot, or changes input to ten by incorrectly attaching the parameterized computation to the same closure. Both trees are really interpreted locally here. Their results do not prove a remote provider uses the same parameter-extraction timing, nor that all referenced objects would be independently copied when the tree is retained.

What a strong answer covers

  • The captured result changes from six to ten.
  • The explicit input three still gives six.
  • MemberAccess identifies a captured-storage dependency.

Common pitfall

Applying closure behavior to the unrelated explicit parameter or assuming a captured value was frozen.

Follow-up questions

  1. What would changing factor to seven produce?
  2. How would a manually embedded constant differ?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions