How to use RuntimeHelpers.IsReferenceOrContainsReferences to micro-optimize collections

 
 
  • Gérald Barré

RuntimeHelpers.IsReferenceOrContainsReferences<T>() is a method that indicates if T is a reference type or contains a reference type. One use case for this method is to micro-optimize collections when removing items. Indeed, if T is a reference type, you need to remove the reference to the item to allow the GC to collect it. If T is a value type, you don't need to do that so you can avoid memory access. This is a very small optimization, but it can be useful in some cases. Note that the JIT will replace the statement with a constant and remove branches that are always false.

Here's an example of a custom list that uses this method:

C#
class CustomList<T>
{
    private readonly T[] _items;
    private int _count;

    public CustomList(int capacity)
        => _items = new T[capacity];

    public void Push(T item)
    {
        if (_count == _items.Length)
            throw new InvalidOperationException("The list is full.");

        _items[_count] = item;
        _count++;
    }

    public T Pop()
    {
        if (_count == 0)
            throw new InvalidOperationException("The list is empty.");

        var value = _items[_count - 1];

        // If T is a reference type or contains a reference type, you need to remove
        // the reference to the item to allow the GC to collect it.
        // For instance, CustomList<string> will need to do that, but CustomList<int> won't.
        // Note: The JIT will remove the if statement if the condition is false, so there is no performance impact.
        if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
        {
            _items[count - 1] = default;
        }

        _count--;
        return value;
    }
}

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub