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;
var values = new ConcurrentDictionary<string, int>(StringComparer.Ordinal);
int calls = 0;
int first = values.GetOrAdd("a", _ => { calls++; return 2; });
int second = values.GetOrAdd("a", _ => { calls++; return 99; });
Console.WriteLine($"first:{first}");
Console.WriteLine($"second:{second}");
Console.WriteLine($"factory-calls:{calls}");
Reveal answer and reasoning
The output is first:2, second:2, and factory-calls:1. The first call sees no a association, runs its factory, and stores two. The second call uses the same key and returns the existing two, so its callback returning ninety-nine is not executed and the counter remains one. The program arranges a sequential reused-key path, not overlapping candidate construction.
The real desktop test uses a barrier inside two callbacks so neither can publish before both factories enter, and there the factory count is two. That does not add another line or race to this portable code. A common wrong answer treats the sequential count as a universal exactly-once guarantee, or predicts ninety-nine because it thinks GetOrAdd overwrites an existing entry.
The API is not an unconditional update, and its factory ownership and exception behavior remain distinct from the association already present.
What a strong answer covers
- The existing value two is reused.
- The second callback is not called in this sequence.
- Concurrent multiplicity needs the separate controlled experiment.
Common pitfall
Turning one sequential cached-key result into a concurrent exactly-once construction guarantee.
Follow-up questions
- What changes if the second key is different?
- Why does the desktop test put the barrier inside the callback?
Self-review
Choose what to revisit. These marks are your own assessment and are separate from lesson completion.