Edit: This post has been rewritten since I first wrote it. I wrote the first edition in frustration and wasn’t to clear on my point.
Lets start with a sample. First we have a method accepting an int[], using the params keyword. It just tries to output them.
static void Dump1(params int[] ids)
{
foreach (var id in ids)
Console.WriteLine(id);
}
Lets consume it
Dump1(1,2,3);
//Outputs
//1
//2
//3
Dump1(new[] { 1, 2, 3 });
//Outputs
//1
//2
//3
Fine. Just what we wanted. The first call passes three values and the second call passes three values, right? No. The last call passes “one” array with three values. But since the Dump1 method accepts params int[], it works.
Now, lets screw things up. Switch params int[] to params object[] and run the same test cases again.
static void Dump2(params object[] ids)
{
foreach (var id in ids)
Console.WriteLine(id);
}
Dump2(1,2,3);
//Outputs
//1
//2
//3
Dump2(new[] { 1, 2, 3 });
//Outputs
//System.Int32[]
System.Int32[]
I guess System.Int32 isn’t exactly what you first expect when writing a method like Dump2. Yes, I know there should have been a failing test, but there wasn’t. But there’s a completly other semantic meaning behind passing an int[] array to an params int[] vs to an params object[] array. Of course it shouldn’t be forbidden, that’s a strong word. But it should at least (per default) generate a squiggle in ReSharper
Now lets finnish with a small tweak. I’ve added a simple recursive extension method. Now we can pass values as we want.
static void Dump(params object[] ids)
{
foreach (var id in ids.Yield()) //Calling extensionmethod
Console.WriteLine(id);
}
public static class Extensions
{
public static IEnumerable<object> Yield(this IEnumerable items)
{
if(items == null)
yield break;
foreach (var item in items)
{
if (item is IEnumerable)
foreach (var o in Yield(item as IEnumerable))
yield return o;
else
yield return item;
}
}
}
Dump(1, 2, 3);
//Outputs
//1
//2
//3
Dump(new[] { 1, 2, 3 });
//Outputs
//1
//2
//3
Dump(new List<int> { 1, 2, 3 });
//Outputs
//1
//2
//3
Dump(new List<int> { 1, 2, 3 });
//Outputs
//1
//2
//3
Dump(1, new[] { 2, 3 }, new[] { new[] { 4, 5 }, new[] { 6, 7 } });
//Outputs
//1
//2
//3
//4
//5
//6
//7
As I said. Off course it should not be forbidden. But, I urge you to think how it will behave when you use params object[].
//Daniel
Sorry, I don’t get it…
Do you mean “Change: params object[] to object”?
I’ve rewritten the post since I first wrote it in anger/frustration. I hope it is more clear now.
//Daniel
Unless I need new glasses I do not see any difference in code Daniel
The difference lied in
params int[]vsparams object[], but I’ve rewritten the post since I first wrote it in anger/frustration. I hope it is more clear now.//Daniel