Search code examples
c#arraysgenericsextension-methods

How to make generic extension method with ref arg in C#


I am trying to remake javascript method "Shift()" to my c# library. The method should return the first item in array and rewrite array to new with correct length. code:

        public static T Shift<T>(this ref T[] array)
        {
            T item = array[0];

            if (array.Length == 1)
            {       
                 array = new T[] { };
                 return item;
            }

            T[] shiftedArray = new T[array.Length - 1];
            for (int i = 1; i < array.Length; i++)
            {
                shiftedArray[i - 1] = array[i];
            }
            array = shiftedArray;

            return item;
        }

I want it to be extension and generic. Any ideas?


Solution

  • shift in js modifies the existing collection, so appropriate approach would be using List<T>. Something like:

    public static T Shift<T>(this List<T> list)
    {
        T item = list[0];
        
        list.RemoveAt(0);
    
        return item;
    }
    

    this ref has a special meaning in C# and can be used with conjunction with structs. For your use case you can see it on special ones - Span and Memory:

    public static T Shift<T>(this ref Memory<T> array)
    {
        T item = array.Span[0];
    
        if (array.Length == 1)
        {       
            array = Memory<T>.Empty;
            return item;
        }
        
        array = array.Slice(1);
    
        return item;
    }
    
    public static T Shift<T>(this ref Span<T> array)
    {
        T item = array[0];
    
        if (array.Length == 1)
        {       
            array = Span<T>.Empty;
            return item;
        }
        
        array = array.Slice(1);
    
        return item;
    }
    

    And usage:

    Span<int> span = new [] { 1, 2, 3 };
    int i1 = span.Shift();
    int i2 = span.Shift();
    

    But usually those are used for special high performance scenarios.