Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is params 'less performant' than a regular array?

If you go right now and type string.Format into your IDE, you'll see that there are 4 different overloads: one taking a string and object, another taking a string and two objects, then one taking three objects, and finally one that uses params. According to this answer, this is because params generates 'overhead', and some other languages may not support it.

My question is, why can't a method call like this:

void Foo()
{
    Bar(1, 2, 3);
}

void Bar(params int[] args)
{
    // use args...
}

Be essentially transformed at compile time to

void Foo()
{
    Bar(new[] { 1, 2, 3 });
}

void Bar(int[] args)
{
    // use args...
}

? Then it wouldn't create any overhead except for the array creation (which was necessary anyway), and would be fully compatible with other languages.

The number of arguments is already known at compile-time, so what's preventing the C# compiler from doing some kind of string substitution and making the first scenario essentially syntactic sugar for the second? Why did we have to implement hidden language features specifically to support variadic arguments?

like image 626
James Ko Avatar asked Nov 06 '25 17:11

James Ko


1 Answers

The title makes an incorrect assumption.

Both a params and a non-params methods take an array; the difference is the compiler will emit the IL to create an array implicitly when making a params method call. An array is passed to both methods, as a single argument.

This can be seen in this .NET Fiddle (view "Tidy Up -> View IL").

using System;

public class Program
{
    public static void Main()
    {
        var a1 = 1;
        var a2 = 2;
        var a3 = 3; 
        with_params(a1,a2,a3);
        no_params(new [] {a1,a2,a3});
    }

    public static void with_params(params int[] x) {}
    public static void no_params(int[] x) {}
}

In both cases the IL is identical; a new array is created, it is populated, and the array is supplied to the invoked method.

There is an "exception" to this identical IL generation in that the compiler can move out constant-valued arrays when used in the non-parameter form and use 'dup' initialization, as seen here. However, a new array is supplied as the argument in both cases.

like image 170
user2864740 Avatar answered Nov 09 '25 09:11

user2864740