2

I'm curious as to why we cannot consume the following method:

void Foo(Bar[] items);

With:

Foo(new Bar());

It would compile and work if the method signature included params

void Foo(params Bar[] items);

I'm sure there are obvious (to some) reasons, I cannot think of any.

EDIT: I understand how the params keyword works - maybe not completely at a low level. I am asking why do we need the keyword params, what are the reasons preventing this implicit cast by default? Granted, this can just be considered a feature request for more syntactic sugar. It may also be expensive for the compiler to include this by default and the cost-benefit isn't there. If so, that's my answer. Maybe my idol Mr. Lippert has a logical reason or can simply say; not possible. Until then, my curiosity get's the better of me.

nullable
  • 2,513
  • 1
  • 29
  • 32
  • When using params the compiler creates the array for you – Pepernoot Oct 13 '16 at 11:05
  • 2
    Possible duplicate of [Why use the params keyword?](http://stackoverflow.com/questions/7580277/why-use-the-params-keyword) – Gilad Green Oct 13 '16 at 11:06
  • Well, an array of some type is something substantially different than an instance of that type. The question why it works if you add `params` is easy to answer: The `params` declaration is **meant** to allow you to pass single values instead of an array, even though it internally looks to you like an array. You could call that synactic sugar or explicitly weakening type safety. If you allowed a single instance to be passed whenever an array is expected, you lose type safety to a certain point. – Thorsten Dittmar Oct 13 '16 at 11:07
  • 2
    It doesn't work like that. It's not the case that every feature where no counterargument has been provided gets implemented. Features need to have arguments in their favour. Is there any reason why your feature should have been implemented? –  Oct 13 '16 at 11:07
  • This can't be added to the language as it is now as it would break a lot of existing code that has overloads for such cases. As to why it wasn't there in C# 1.0, well, I guess you'd have to ask Anders Hejlsberg directly. And by extension the designers of Java as well. – Jeroen Mostert Oct 13 '16 at 11:07
  • @CodeJoy I understand that. I'm not questioning that. Why does the CLR not allow it without the params keyword? – nullable Oct 13 '16 at 11:07
  • 1
    @Kurt The CLR doesn't allow it at all, ever. The CLR requires an array. The `params` keyword lets the compiler add some extra code that creates the array. The CLR doesn't create it automatically. –  Oct 13 '16 at 11:08
  • Because it is not designed like that. The `params` syntax is the exception to the rule here, not the other way. It is a compiler feature, not some runtime automatism. – Thorsten Dittmar Oct 13 '16 at 11:08
  • @hvd This might be the answer I'm looking for. Granted, it's just syntactic sugar. It seems it has been desired - hence a params keyword was implemented. – nullable Oct 13 '16 at 11:11
  • 1
    Its not so much a CLR issue as a functionality one @hvd. `params` *expicitly* makes the argument *optional*. `Foo(params int[] values)` allows the call `Foo()` becuase you've informed the compiler you want it to be so. According to the OP's proposal, signatures like`Foo(Fooable[] f)` would either need to implicitly make the call `Foo()` valid (which is disaster waiting to happen), or disallow it altoghether which would entail loosing functionality. Hence the keyword. – InBetween Oct 13 '16 at 12:51
  • @InBetween That comment was a response specifically to the OP's "Why does the CLR not allow it without the params keyword?" And yes, if the OP was proposing that every array parameter would be treated the way `params` parameters are treated now, then I agree with you. I don't know if that was what the OP was proposing. I see multiple possible interpretations. Not all of them have the problem you describe, but they do have other problems. –  Oct 13 '16 at 12:59
  • Another obvious reason why `params` is needed is signatures of the type `Foo(int[] ints, object[] objects)`. How would your proposal handle `Foo(1, 1, 1)`? `Foo(int[] ints, param object[] objects)` would disallow that call because the argument types wouldn't match. You'd have to call it as `Foo(new[] { 1 }, 1 , 1)` which is unambiguous. Etc. – InBetween Oct 13 '16 at 13:13
  • This looks like an @eric-lippert question. – cchamberlain Oct 13 '16 at 14:10
  • 2
    When asking questions like this, ask yourself the question "why am I concerned only about arrays?" Should there also be a conversion from `T` to `IList`? `List`? `HashSet`? `ImmutableSet`? `ICollection`? `IEnumerable`? `IEnumerator`? `Func`? `Task`? `Lazy`? `IObservable`? `Nullable`? (OK C# does give you the last one!) Sure, converting from a T to T[] is easy, but *all* those conversions I just described are equally easy. If there is an argument for one of them then perhaps it applies to all of them. Would you like all those conversions? – Eric Lippert Oct 13 '16 at 19:54
  • *Starstruck* I should have been more explicit. I was actually only concerned about IEnumerable. In any case, I see your point, my only argument would be in favour of syntactic sugar. Which I now know is rendered ridiculous. Now I can continue writing overloads and abusing the params keyword, happily, with the thought "Eric Lippert commented". Thanks for your comment and all your contributions! – nullable Oct 13 '16 at 22:22
  • @eric-lippert - When asking questions like this, I recommend closing Visual Studio and switching over to JavaScript where you can color outside the lines. :) – cchamberlain Oct 14 '16 at 06:16
  • 1
    @EricLippert: I realize your question was pedagogical, but it's worth noting the Roslyn design notes do discuss this. E.g., see the May 21, 2014 design notes at http://roslyn.codeplex.com/discussions/546466 . So, this is a "why" question where there is less need to speculate on what the designers were thinking (though I admit it's still speculation, since we don't have the original design notes). While plenty of people are excited about Microsoft releasing source code, releasing design notes is also exciting. – Brian Oct 14 '16 at 13:39
  • So now start thinking about ways that things can go horribly wrong. Suppose we have `class B {} class D : B, IEnumerable{...}` and `B d = new D();`. Now we say `IEnumerable b1 = (IEnumerable)d; IEnumerable b2 = d;` The former works because we check at runtime that `d` actually refers to an instance of `D`. The latter works because `B` is convertible to `B[]` and `B[]` is convertible to `IEnumerable`. Do you find it surprising that not only are b1 and b2 unequal, they do not even refer to objects of the same type? – Eric Lippert Oct 14 '16 at 23:43

1 Answers1

0

Since the params keyword creates an array of Bar which is filled by the compiler with your single instance of Bar. If you define an array of Bar by your self then the compiler thinks "Ok, this is not my concern. The programmer will take care to provide the needed type when calling the function"

Pepernoot
  • 3,409
  • 3
  • 21
  • 46
Radinator
  • 1,048
  • 18
  • 58
  • k then how's that: Using the **param** keyword enables you (as programmer/user of this lib) to decide wether using a array, multiple values or just on single parameter. Whereas using explicitly the array as parameter type forces you (as programmer/user of this lib) to provide a array – Radinator Oct 13 '16 at 11:25
  • 1
    I'm not question how the **params** keyword works. Please see my edit. I would like to know if there are any logical reasons as to why the compiler needs to see a params keyword. Why can't an implicit conversion from T to T[] exist? – nullable Oct 13 '16 at 11:31