In this article, we’ll have a look at the params keyword in C#. We’ll discuss the use cases and best practices.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in!

What Is the ‘Params’ Keyword?

params is a special keyword that allows passing a variable number of parameters into a method. It allows a nice, flexible syntax that helps us specify:

  • One or multiple parameters separated by commas (that’s the ‘killer feature’)
  • No parameters at all
  • A single parameter of a single-dimensional array type

Let’s see how it looks.

First, we define a method that accepts the params argument:

public class ShoppingList
{
    public void Add(params string[] items)
    {
        foreach (var item in items)
        {
            Console.WriteLine($"Added: {item}");
        }
    }
}

The params keyword has to be followed by a single-dimensional array.

Within the method body, it doesn’t matter that the values were passed as a params argument. This is completely transparent, and the variable behaves exactly like any other array variable.

Let’s have a look at the various valid ways of calling this method. First off, the ‘free flow’ of arguments:

var shoppingList = new ShoppingList();
shoppingList.Add("Bananas", "Grapes", "Ham", "Cheese");
shoppingList.Add("Headphones");

As you can see, we can add one or many arguments directly within the method, without declaring any collections to wrap the parameters. 

Secondly, we can also call the method with a single parameter – a single-dimensional array of the type specified in the signature:

var groceries = new [] { "Bananas", "Grapes", "Ham", "Cheese" };
shoppingList.Add(groceries);

Lastly, it’s perfectly acceptable to not pass any value and omit the argument completely:

shoppingList.Add();

Notice that in this case, the value of the argument is an empty array. Omitting the argument does not pass a null value. However, it is possible to pass a null params argument to the method – and in that case, the argument will be null in the method body too.

Adding the ‘Params’ Keyword to a Method Signature

There are a few conditions for adding a params argument to a method:

  • It has to be the last argument in the method signature
  • There can be only one params argument
  • It has to be an array (other collection types are not permitted)
  • It cannot have a default value assigned

We can, however, combine params arguments with other parameters in the method body, even of the same type. Consequently, the following method signatures are perfectly valid:

public void StringBeforeStringParams(string requiredStringArgument, params string[] items)

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

In this case, the compiler will expect at least one string passed to the method. It will treat all the following strings as values for the params argument.

We can also declare multiple arrays of the same type:

ArrayBeforeParams(string[] requiredArray, params string[] items)

The method above can be called in two ways:

ArrayBeforeParams(new[] {"Required", "Array"}, "And", "Free", "Arguments")
ArrayBeforeParams(new[] {"Required", "Array"},  new[] {"And", "Array", "For Params"})

We can also specify optional arguments in the method signature:

void OtherArgumentsBeforeParams(int requiredParam, bool optionalBool = true, params string[] items)

Notice that here, even though we have specified the boolean parameter as optional, we cannot omit it when calling the method:

OtherArgumentsBeforeParams(2, "Ooops", "Doesn't", "compile!");

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

The code above will show the “Cannot convert from ‘string’ to ‘bool’” error until we explicitly specify a value for the optionalBool argument:

OtherArgumentsBeforeParams(2, true, "Yeah", "Now", "All good");

Another thing worth mentioning is that params doesn’t work well with named arguments:

UseParamsWithNamedArguments(int firstArgument, params string[] items){ ... } 

UseParamsWithNamedArguments(firstArgument: 10, items: "Ooops", "Doesn't", "Compile");

The sample above shows a “No overload for method takes 4 arguments” compiler error. In order to use named arguments, we need to wrap the comma-separated values into an array:

UseParamsWithNamedArguments(firstArgument: 10, items: new [] { "Now", "all", "good"} );

Why Use the ‘Params’ Keyword?

As mentioned, using the params keyword adds a bit of flexibility and it can make our methods more user-friendly.

On the other hand, it has some downsides. It introduces some ambiguity in methods that take multiple parameters because it’s less explicit about what methods require.

A significant problem with this happens when a method signature changes (e.g. someone adds or removes an argument). The calling code might still compile, but assign incorrect values to arguments where we used params argument with a comma-separated list of values. This is especially dangerous in case of params object[] because this argument type will accept any value type.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

For this reason alone, the benefits of this keyword are rarely worth the risk, especially in public-facing APIs.

Conclusion

In this article, we’ve covered the params keyword along with several ways of using it. We’ve also mentioned the risks that are associated with this feature.

As always, we are responsible for choosing the right tools for the job, and hopefully, this article helps make an informed decision about using this feature. For other similar guidelines, be sure to check out our C# basics series.