By Mickael Thumerel


2018-09-14 15:23:11 8 Comments

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 a struct?

  • 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?

3 comments

@gabba 2018-09-14 15:38:32

  1. tiny structs are more fast if no boxing occurred. (by my tests its 7-20 times faster to make similar objects as structs). But better do a tests!
  2. depends on count objects, but yes structure will make less side cost
  3. no there are no way to inform GC, only internal heuristics will be used

so code will be look like this, be careful you must check case when TryEnterReadLock return false :

        var _storageLocker = new ReaderWriterLockSlim();

        using (var lockContext =new ReadLockContext(_storageLocker))
        {
            if (lockContext.IsAcquired)
            {

            }
        }

public struct ReadLockContext : IDisposable
{
    private readonly ReaderWriterLockSlim locker;

    public ReadLockContext(ReaderWriterLockSlim locker, TimeSpan timeout = default(TimeSpan))
    {
        if (timeout == default(TimeSpan))
            timeout = TimeSpan.FromMilliseconds(-1);

        if (locker.TryEnterReadLock(timeout))
            this.locker = locker;
        else
            this.locker = null;
    }

    public bool IsAcquired => locker != null;

    public void Dispose()
    {
        locker?.ExitReadLock();
    }
}

@sjb-sjb 2018-09-15 03:46:54

Use a struct and don't mess around with the garbage collector.

Note the translation of 'using' does not box the variable even though it implements the IDispose interface.

@Farrukh Waheed 2018-09-14 15:31:35

From the answer in the post What are the uses of "using" in C# :

The reason for the "using" statement is to ensure that the object is disposed as soon as it goes out of scope, and it doesn't require explicit code to ensure that this happens.

Structs are Value Types and Classes are Reference types, and I think, with "using" statement, it doesn't matter as it would be destroyed as soon as it goes out of scope.
You can find some good discussion on the use of IDispose/Finalize things in Finalize/Dispose pattern in C#

Related Questions

Sponsored Content

11 Answered Questions

[SOLVED] Do HttpClient and HttpClientHandler have to be disposed?

18 Answered Questions

[SOLVED] What's the difference between struct and class in .NET?

9 Answered Questions

[SOLVED] How to get the list of properties of a class?

28 Answered Questions

[SOLVED] When to use struct?

  • 2009-02-06 17:37:55
  • Alex Baranosky
  • 230588 View
  • 1224 Score
  • 28 Answer
  • Tags:   c# struct

0 Answered Questions

4 Answered Questions

[SOLVED] How do I convert struct System.Byte byte[] to a System.IO.Stream object in C#?

  • 2011-01-19 14:08:58
  • Mehdi Hadeli
  • 425337 View
  • 573 Score
  • 4 Answer
  • Tags:   c# .net arrays stream

16 Answered Questions

[SOLVED] How to get the type of T from a member of a generic class or method?

  • 2009-02-17 15:24:36
  • Patrick Desjardins
  • 513506 View
  • 562 Score
  • 16 Answer
  • Tags:   c# .net generics

6 Answered Questions

[SOLVED] How to manage IDisposable Objects that are cached?

2 Answered Questions

[SOLVED] Using specific patterns to implement interfaces

2 Answered Questions

[SOLVED] How to implement dispose pattern with close method correctly (CA1063)

  • 2009-03-10 16:03:03
  • dtb
  • 6471 View
  • 12 Score
  • 2 Answer
  • Tags:   c# fxcop

Sponsored Content