|Your second example should look something like:
theValue = concurrentDict.GetOrAdd(theKey, key =>
var theNewObject = NewUpAnObject(key);
The entire delegate would be executed within the scope of a lock, as with your non-generic dictionary code. However, the lock would be more granular, based on the number of buckets and the concurrency level of the collection.
If you wanted to execute the "other stuff" outside of the lock, your code would look like:
if (!concurrentDict.TryGetValue(theKey, out theValue))
var theNewObject = NewUpAnObject(theKey);
theValue = concurrentDict.GetOrAdd(theKey, theNewObject);
In this case,
NewUpAnObject would run outside of any lock. However, the insert to the dictionary would not suffer from a race condition, as the class is specifically written to cope with this type of code.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."