C#, Why params object[] should be forbidden! (v2)

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

Advertisement

5 thoughts on “C#, Why params object[] should be forbidden! (v2)

    • I’ve rewritten the post since I first wrote it in anger/frustration. I hope it is more clear now.

      //Daniel

    • The difference lied in params int[] vs params object[], but I’ve rewritten the post since I first wrote it in anger/frustration. I hope it is more clear now.

      //Daniel

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s