Search code examples
c#performance.net-core

Convert List OR Array to Span


I'm working on an internal library that needs to support both lists and arrays. This is a hot path so we're looking at performance improvements.

Currently it's using IList<T> in the parameters, as we require index based access in the library, and to avoid re-writing it for both types.

public int Foo<T>(IList<T> values);

A pretty free performance improvement (measured and benchmarked) would be to convert it to a span internally, which we could do just by making some overloads that convert the value and pass it on immediately, but it feels like there should be a cleaner way. I'm not a big fan of having a lot of stubs, especially when it seems like they're doing a very similar thing.

public int Foo<T>(T[] values)
    => Foo(values.AsSpan());

public int Foo<T>(List<T> values)
    => Foo(CollectionsMarshal.AsSpan(values));

private int Foo<T>(Span<T> values)

Is there any interface/marshal that can be used for both a List and an Array that converts them to a Span?


Solution

  • There is no way of using the same AsSpan() method for Lists and Arrays, other than creating your own AsSpan() Extension. Instead you could always use IList<T>:

    public int Foo<T>(IList<T> list)
    {   
        Span<T> span;
    
        if (list is T[] array)
        {
            span = array.AsSpan();
        }
        else if (list is List<T> concreteList)
        {
            span = CollectionsMarshal.AsSpan(concreteList);
        }
        else 
        {
            throw new NotSupportedException("not supported!");
        }
    
        return Foo(span);
    }
    
    private int Foo<T>(Span<T> values)
    {
        // ...
    }