-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Problem
A fairly common occurrence when working with locks is to use double-checked locking to avoid acquiring the lock when it won't be necessary. However implementing this requires both a duplication of the condition and requiring statements inside the lock to be indented by three levels:
if (condition)
{
lock(lockObj)
{
if (condition)
{
// statements
}
}
}
Even if we eliminate the brackets on the outer if and the lock and place them on the same line to reduce indentation, it gets to be a mess very quickly except with the shortest and most trivial of conditions:
if (condition) lock(lockObj) if (condition)
{
// statements
}
Solution
In order to alleviate this, I'd propose combining the construct in a similar way to catch filters:
lock(lockObj) if (condition)
{
// statements
}
However, this is already valid C#, so would impact backwards-compatibility. Instead, I'd suggest using when in place of if; It still reads off quite naturally, and is only a contextual keyword:
lock(lockObj) when (condition)
{
// statements
}
As far as I can tell, this can't compile under C# 5/6, though I'm sure someone can find a counter-example ;)
I don't see developers 'abusing' the condition in the same way they might on catch (e.g. logging taking a lock) as they can already do this just before the lock is taken, but some might disagree!
I see the main problem being if a developer unsuspectingly uses a non-pure/side-effecting condition without realising it will be evaluated twice, but I'd hope good documentation would avoid this.
It's not the most pressing of concerns and doesn't really afford us any new expressiveness, but does follow nicely the current trend of reducing boilerplate by making certain parts of the language more concise, and appears to be a relatively simple lowering transformation.