Skip to main content

How to Resolve Error "CS0231: A params parameter must be the last parameter in a formal parameter list" in C#

The Compiler Error CS0231 is a syntax restriction error involving the params keyword. The message reads: "A params parameter must be the last parameter in a formal parameter list."

In C#, the params keyword allows a method to accept a variable number of arguments. The compiler handles this by "scooping up" all remaining arguments provided by the caller and bundling them into a collection (historically an array). Because params is designed to consume "everything else," it must be the absolute last item in your method definition. If you place another parameter after it, the compiler cannot determine where the variable arguments end and the fixed argument begins.

This guide explains the mechanics of argument resolution and how to order your parameters correctly.

Understanding the "Greedy" Nature of params

When the compiler encounters a method call like Sum(1, 2, 3, 4), and the method is defined with params int[], the compiler tries to fit as many arguments as possible into that array.

If C# allowed this signature: void Method(params int[] numbers, int limit), and you called Method(1, 2, 3, 4), it is ambiguous:

  • Does numbers contain [1, 2, 3] and limit is 4?
  • Does numbers contain [1, 2, 3, 4] and limit is missing?

To avoid this guessing game, the rule is strict: The params array captures the tail end of the argument list. Nothing can follow it.

Scenario 1: Placing Parameters After params

This is the most common mistake. You realize you need an extra argument (like a flag or a message), so you add it to the end of the method signature, forgetting that params was already there.

Example of error

public class Logger
{
// ⛔️ Error CS0231: A params parameter must be the last parameter.
// The compiler doesn't know when 'values' stops and 'logLevel' begins.
public void LogData(params int[] values, string logLevel)
{
// ...
}
}

Solution: Reorder the Parameters

Move the fixed parameter (logLevel) to the beginning of the list.

public class Logger
{
// ✅ Correct: 'logLevel' is fixed (1st argument),
// 'values' takes everything else (2nd argument onwards).
public void LogData(string logLevel, params int[] values)
{
System.Console.WriteLine($"Level: {logLevel}, Count: {values.Length}");
}
}

// Usage:
// logger.LogData("INFO", 1, 5, 10);

Scenario 2: Interaction with Optional Parameters

C# allows Optional Parameters (parameters with default values). You might think that because optional parameters can be omitted, they might be allowed after params. This is incorrect.

Even if a parameter has a default value, params must still be physically the last item in the declaration.

Example of error

public class Calculator
{
// ⛔️ Error CS0231: Even though 'multiplier' is optional,
// it cannot come after 'params'.
public void Add(params int[] numbers, int multiplier = 1)
{
}
}

Solution: Reorder (and potentially overload)

You must place optional parameters before the params array.

public class Calculator
{
// ✅ Correct: Optional parameter comes first.
public void Add(int multiplier = 1, params int[] numbers)
{
// ...
}
}
note

Calling Ambiguity: If you use the solution above (Add(int multiplier = 1, params int[] numbers)), calling Add(5) is valid.

  • multiplier becomes 5.
  • numbers becomes an empty array. If you wanted multiplier to use the default 1 and 5 to be part of numbers, you would have to call Add(1, 5).

Conclusion

CS0231 ensures that method calls are deterministic.

  1. Check the Order: Look at your method signature.
  2. Move params: Cut the params parameter and paste it at the very end of the list.
  3. Only One: Remember, you can have only one params parameter per method, and it must always be the caboose of the train.