2

How does c# make params work.

When you have code like

 static string Concat(int arg)
 {
     return arg.ToString();
 }

static string Concat(int arg, params string[] p)
{
    string result = string.Empty;
    result = result + arg.ToString();
    foreach (var s in p)
    {
        result = result + s;
    }
    return result;
}

Resharper says the method with params hides the other method. Does this imply that under the hood The other method is being defined and calling the one with params passing in an empty array? Or something else entirely?

(please don't get bogged down on the crappy code - its just an example)

Edit to explain:

If i do not define the static string Concat(int arg) method i can still call the second as

var s = Concat(123);

despite that method not being defined .... so the question is: is the first method defined implicitly under the hood and calling the second with an empty array. Note i changed the arg type from string to int.

to explain the weirdness as i see it. When you call as above ... it hits the params object with an empty array, the param is not null - which is what i expected. When i first wrote that foreach loop i had a null check on params then discovered i didn't need it.

So ... you reason that it must be wrapping any params after the first parameter in an array right? A little bit of inlined code? ... so if you passed in "dave" you would get freddave as the output ....

However pass null into it ....

static void Main(string[] args)
{
    Console.WriteLine(Concat("fred",null));
}

 //static string Concat(string arg)
 //{
 //    return arg;
 //}

static string Concat(string arg, params int[] p)
{
    string result = string.Empty;
    result = result + arg;
    if (p != null)
    {
        foreach (var s in p)
        {
            result = result + s.ToString();
        }
    }

    return result;
}

and you discover in this case p is actually null ... If you do that with the string example ... id of expected an array with 1 element of null ... instead the entire params object is null.

John Nicholas
  • 4,778
  • 4
  • 31
  • 50
  • i don't think it quite is. But that one does have an answer ... i have edited to make my point. I get how the overloads are selected in this case. – John Nicholas Oct 04 '13 at 09:08
  • Your question doesn't quite make sense now. You claim: "i can still call the second as `var s = Concat("foo");`" - but you can't, because you're not providing the mandatory `int` argument. – Jon Skeet Oct 04 '13 at 10:52
  • fixed the code in the text to match the signatures – John Nicholas Oct 08 '13 at 09:03

1 Answers1

4

I think calling it "hiding" is misleading here, to be honest.

Both methods are definitely created, but if you call:

Concat(5);

then for that invocation both methods are applicable (in the terminology of the C# spec section 7.5.3.1) but the first method is better (section 7.5.3.2) because of this:

  • Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ.

So in that case, the first method would be called.

The second method cannot be called using params expansion without specifying at least one string. It can still be called with an empty array, of course:

Concat(5, new string[0]);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • sorry, good answer ;) my bad question. I forgot to ask the starting point of the investigation and only showed the end. – John Nicholas Oct 04 '13 at 09:11
  • @JohnNicholas: I'm not sure whether or not I've answered your updated question (which changed the types involved for no obvious reason...). As for your expectation of the array being null - that would be needlessly annoying for implementations, I think. – Jon Skeet Oct 04 '13 at 09:26
  • I changed the types as I was wondering if id get a compile error with the int array (whilst talking with someone about it). As the entire array is null made no difference. It just eliminated one theory. I don't think you have quite answered the question. Sorry. Am tempted to hunt about to see if we have a reflector license here. I suspect the reason why it behaves like this is how you say however. – John Nicholas Oct 04 '13 at 09:30
  • @JohnNicholas: Are you intending to change the question any more? If not, I'll take a look at answering it again - but I'm not going to waste time on an ever-changing question that I can never actually answer... – Jon Skeet Oct 04 '13 at 10:51
  • yeah sorry. Final version now :D. An answer would be greatly appreciated, still find the situation curious. – John Nicholas Oct 08 '13 at 09:04
  • @JohnNicholas: To be honest, it's still unclear what you're actually asking. I suggest you read section 10.6.1.4 of the C# spec though, which may clarify things. I'll see if I can find time to update my answer later. – Jon Skeet Oct 08 '13 at 09:10