Receive indefinite amount of parameters in C#

Asked

Viewed 2,674 times

7

The method Main(string[] args) receives an array of indefinite amount parameters. But I know this doesn’t work in a common method. How to create a method that takes as many parameters as needed?

  • 2

    There is a misconception in your question, if it were not possible as the function Main would you? @Lucas Nunes' reply is correct, but it is possible to do it both ways. There is a difference between receiving an array of undetermined size and receiving an undetermined amount of parameters.

  • @Cahe I edited the answer adding some details. In the case, the Main already receives a string[] properly treated as methods with params has the arguments converted at compile time to something like new int[] {1,2,3}, and function as a int[] normal.

  • My purpose is simple: give the user the freedom to enter as many values as he wants to add, or multiply, for example. params, as taught by @Lucas Nunes, seems to be the most correct, but if there are other ways, please submit as a response or even comment. The important thing is that we learn.

2 answers

7


You can do this using the keyword params.
With it you define a parameter that uses several arguments or none.

For example:

    private static int Somar(params int[] values)
    {
        int sum = 0;

        for (int i = 0; i < values.Length; i++)
        {
            sum += values[i];
        }

        return sum;
    }

And with that, you can call Somar() as follows:

    static void Main(string[] args)
    {
        Console.WriteLine("O resultado da soma é " + Somar(1, 2, 3, 4, 5));
        Console.WriteLine("Outro resultado da soma é " + Somar(10, 20, 4));
        Console.WriteLine("Quando não soma nada é " + Somar());

        Console.Read();
    }

It should be noted that the parameter with params should be the last one in the function. For example:

// A seguite declaração é inválida:
private static void Imprimir(params int[] valores, string titulo) { }

// Já essa é válida (pois params vai por último):
private static void Imprimir(string titulo, params int[] valores) { }

Another important detail is that the compiler will give priority to the specialized version of the method (if it exists).

For example, if you have the following methods defined:

private static int Somar(int a, int b) { }
private static int Somar(params int[] values) { }

and call Somar(10, 20), the compiler will give priority to the first.


Another special case is when you want to use params for various types. In this case, the object instead of the specific type.

An example is the following:

public static void ImprimirLista(params object[] list)
{
    for (int i = 0; i < list.Length; i++)
    {
        Console.Write(list[i] + " ");
    }

    Console.WriteLine();
}

That is applied thus:

ImprimirLista(10, "String", 20.4);

When you compare the methods they use params the methods they do not use params, the keyword should be considered params is handled by the compiler so that when called Somar(2, 3, 4), the compiler turns into Somar(new int[]{2,3,4}). Without params, the compiler will not make this consideration and will require that a int[].

Therefore, the definition of the following methods will result in a conflict as they are equivalent:

 public static void ImprimirLista(params int[] list) {}
 public static void ImprimirLista(int[] list) {}

5

Lucas Nunes' answer is correct and well completed. I will only offer alternatives that can be useful to other people today and in the future.

It may not be necessary to have a completely undetermined number of parameters. You may have a variable amount but have a small maximum limit. What’s more, each parameter has a different type known. There are some alternatives in these cases.

void M(int p1 = 1, string p2 = "", bool p3 = true, int p4 = 0) { ... }

This form uses optional Arguments. Then in the method call it is possible to use only the parameters that are not equal to the values default. Ex.:

M(2); //na prática chama M(2, "", true, 0)

It is also possible to use the call via named Arguments:

void M(p1: 1, p4: 0, p3: true)

There is still a way to pass parameters this way explicitly:

void M(Tuple<int, string, bool, int> p) { ... }

The call would go:

M(new Tuple<int, string, bool, int>(3, "teste", false, 1));

In C# it is also possible:

M(new Tuple(3, "teste", false, 1));

In some situations you may not want to receive exactly one array. There are proposals to use a enumerable type, almost entered in C# 6 and 7. Who knows in 8.

void M(params IEnumerable<int> p) { foreach(int i in p) Console.WriteLine(i); }

In the C# 7 has tuples in the language which may further facilitate:

void M((int valor, string nome, bool status, int outro) p) { ... }

The call would go:

M((3, "teste", false, 1));

I put in the Github for future reference.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.