Search code examples
pythonc#parametersarguments

Is there an equivalent unpacking operation in C# as in Python


In the following python example we have a function which accepts a variable number of non-keyworded arguments and a possible function call:

def print_numbers(*list_of_numbers):
    for i in list_of_numbers:
        print(i)
        

print_numbers(1,2,3,4, *[5,6], *[7,8], 9)

In C# we have the params keyword which allows a variable number of arguments. Now I am curious whether in C# we can come up with something similar as in Python. The following example shows how close I got to the desired usage.

void Foo(params int[] liste)
{
    foreach(var item in liste)
    {
        Console.WriteLine(item);
    }
}


var array = new int[] {1, 2, 3, 4};

// allowed
Foo(array);

// compiler error CS1503
// Foo(array, 5, 6);

Solution

  • You can solve the problem with extension methods. These methods would take either a single value or an array and add additional items given as params:

    public static class MixedParamsExtensions
    {
        public static T[] Pack<T>(this T item, params T[] args)
        {
            var ret = new T[args.Length + 1];
            ret[0] = item;
            Array.Copy(args, 0, ret, 1, args.Length);
            return ret;
        }
    
        public static T[] Pack<T>(this T[] array, params T[] args)
        {
            var ret = new T[array.Length + args.Length];
            Array.Copy(array, 0, ret, 0, array.Length);
            Array.Copy(args, 0, ret, array.Length, args.Length);
            return ret;
        }
    }
    

    Given this method:

    public static void print_numbers(params int[] args)
    {
        foreach (var item in args) {
            Console.WriteLine(item);
        }
    }
    

    you could do the call:

    print_numbers(1.Pack(2, 3, 4).Pack(new[] { 5, 6 }).Pack(new[] { 7, 8 }).Pack(9));
    

    This is the closest I can come to the python equivalent:

    print_numbers(1,2,3,4, *[5,6], *[7,8], 9)
    

    C# 12 added Collection expressions. You could write this equivalent code:

    int[] a = [5, 6];
    int[] b = [7, 8];
    print_numbers([1, 2, 3, 4, .. a, .. b, 9]);
    

    The doc linked above says: You use a spread element .. to inline collection values in a collection expression.