You are looking the same key up twice

ContainsKey then the indexer is two searches.

You are looking the same key up twice

The problem

Two searches for one answer.

if (scores.ContainsKey(name)){    var score = scores[name];    Show(score);}

ContainsKey hashes the key and walks the bucket. The indexer does the whole thing again.

The fix

Ask once, get both answers.

if (scores.TryGetValue(name, out var score)){    Show(score);}

TryGetValue returns whether it was there and hands you the value in the same lookup.

The same shape elsewhere

Most collections have a Try.

Any time you check then fetch, look for the paired call.

Dictionary
TryGetValue
Queue and Stack
TryDequeue, TryPop
Parsing text
int.TryParse

Each one replaces a check plus a fetch, or a try plus a catch.

The rule

Check and fetch is one call, not two.

ContainsKey then []
two lookups
TryGetValue
one lookup
In a loop
the difference doubles

out var declares it right there in the if.