Will `params` in C# always cause a new array to be allocated on every call?
<p>C#/.NET has variadic function parameters by passing an <code>Array</code> type by-reference (as opposed to C/C++ which just places all of the values directly on the stack, for better and for worse).</p>

<p>In the C# world this has a neat advantage of allowing you to call the same function with either 'raw' arguments or a reusable array instance:</p>

<pre><code>CultureInfo c = CultureInfo.InvariantCulture;

String formatted0 = String.Format( c, "{0} {1} {2}", 1, 2, 3 );

Int32 third = 3;
String formatted0 = String.Format( c, "{0} {1} {2}", 1, 2, third );

Object[] values = new Object[] { 1, 2, 3 };
String formatted1 = String.Format( c, "{0} {1} {2}", values );
</code></pre>

<p>This means that the generated CIL is equivalent to:</p>

<pre><code>String formatted0 = String.Format( c, "{0} {1} {2}", new Object[] { 1, 2, 3 } );

Int32 third = 3;
String formatted0 = String.Format( c, "{0} {1} {2}", new Object[] { 1, 2, third } );

Object[] values = new Object[] { 1, 2, 3 };
String formatted1 = String.Format( c, "{0} {1} {2}", values );
</code></pre>

<p>Which means that (in a non-optimizing JIT compiler) <strong>every call will allocate a new <code>Object[]</code> instance</strong> - though in the third example you're able to store the array as a field or other reusable value to eliminate the new allocation on <em>every</em> call to <code>String.Format</code>.</p>

<p>But in the official CLR runtime and JIT are any optimizations done to eliminate this allocation? Or perhaps is the array tagged specially so that it will be deallocated as soon as execution leaves the scope of the call-site?</p>

<p>Or, perhaps, because the C# or JIT compiler knows the number of arguments (when used "raw") could it do the same thing as the <code>stackalloc</code> keyword and place the array on the stack, and thus not need to deallocate it?</p>