I had the habit to implement some scope lock pattern using the "Using" statement.
Example:
ReaderWriterLockSlim _storageLocker
using (_storageLocker.LockRead())
{
// do suff
}
In this example the extension method LockRead create a specific IDisposable object that will lock in construction and release when disposed.
/// <summary>
/// Scope lock pattern that lock the current <see cref="ReaderWriterLockSlim"/> in read mode
/// </summary>
public static IDisposable LockRead(this ReaderWriterLockSlim locker, TimeSpan timeout = default(TimeSpan))
{
if (timeout == default(TimeSpan))
timeout = s_defaultTimeout;
var isLocked = locker.TryEnterReadLock(timeout);
if (isLocked)
return new ScopeLockAction<ReaderWriterLockSlim>(l => l.ExitReadLock(), locker);
return Disposable.Disposed;
}
This pattern is useful and cleaner than try/Finally
but the sad point is that it create a new instance each time you lock.
The ScopeLockAction
implement correctly the IDispose
pattern and called the GC.SuppressFinalizer()
to little bit optimize the recycling.
I know that .NET garbadge collector implements some recycling mechanism that permit him to reuse an allocated space for future same Type Instances.
My questions are:
When you have small instance with fixed size that will be often create and dispose, and only used with the using statement (it means no boxing), is it's more performant to use a
class
or astruct
?Does it make any difference?
Is there a way to inform the garbadge collector that it could recycle the instance space for another instance of the same type?