简体   繁体   中英

How exactly keyword 'params' work?

The following code sample prints:

T
T[]
T[]

While first two lines are as expected, why compiler selected param array for a regular array?

public class A
{
    public void Print<T>(T t)
    {
        Console.WriteLine("T");
    }

    public void Print<T>(params T[] t)
    {
        Console.WriteLine("T[]");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        a.Print("string");
        a.Print("string","string");
        a.Print(new string[] {"a","b"});
    }
}

Under the hood

a.Print("string","string");

is just syntactic sugar for

a.Print(new string[]{"string","string"});

EDIT: Like I said, the params keyword only automagically creates the array for you, you tell the compiler: either accept an array of T directly or use the X input params to construct that array.

It addition to what others have said, the params keyword also causes a ParamArrayAttribute to the generated for array parameter. So, this...

public void Print<T>(params T[] t) { }

Is generated by the compiler as...

public void Print<T>([ParamArray] T[] t); { }

It is that attribute which indicates to the compiler and the IDE that the method can be called using simpler syntax...

a.Print("string", "string");

rather than...

a.Print(new string[] { "string", "string" });

Params allows you to pass multiple objects of the same type. it is a shortcut way of passing array

I think this actually has more to do with type inference than with the params keyword. The inference engine assumes on the third line that the type of T is string[] and therefore passes it to the first method.

try Console.WriteLine(typeof(T)) if you don't believe me

when having the params keyword, the compiler will do a little bit of translation for the formal function declaration, as well as the actual function call.

Formal function declaration:

Under the hood, the IL will be translated to essentially the same as

public void Print<T>(T[] array);

Except, when compiling, the actual function call will be checked for syntax translation. Meaning,

a.Print("string1", "string2");

Becomes the same IL code as

a.Print(new string[]{"string1", "string2"});

That is why line 2 and 3 are the same output, because under the hood, they got translated to the exact same IL.

Question about why line 3 is not print "T" is because, .NET compiler will always try to find the best overloaded match, and so both line 2 and 3 called to the T[] version instead of the plain T.

Exactly as arul said. If you open up the project in reflector, you'll see the following:

a.Print<string>(new string[] { "string", "string" });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM