Argumentos nomeados e opcionais (Guia de Programação em C#)

Os argumentos nomeados permitem que você especifique um argumento para um parâmetro correspondendo o argumento com seu nome em vez de com sua posição na lista de parâmetros. Argumentos opcionais permitem omitir argumentos para alguns parâmetros. Ambas as técnicas podem ser usadas com os métodos, indexadores, construtores e delegados.

Quando você usa argumentos nomeados e opcionais, os argumentos são avaliados na ordem em que aparecem na lista de argumentos e não na lista de parâmetros.

Parâmetros nomeados e opcionais permitem que você forneça argumentos para parâmetros selecionados. Essa capacidade facilita bastante chamadas para interfaces COM como as APIs de Automação do Microsoft Office.

Argumentos nomeados

Os argumentos nomeados liberam você da necessidade de combinar a ordem dos argumentos com a ordem dos parâmetros nas listas de parâmetros de métodos chamados. O argumento para cada parâmetro pode ser especificado pelo nome do parâmetro. Por exemplo, uma função que imprime detalhes de pedidos (como o nome do vendedor, nome do produto e número do pedido) pode ser chamada por meio do envio de argumentos por posição, na ordem definida pela função.

PrintOrderDetails("Gift Shop", 31, "Red Mug");

Se não se lembrar da ordem dos parâmetros, mas souber os nomes, você poderá enviar os argumentos em qualquer ordem.

PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);

Os argumentos nomeados também melhoram a legibilidade do código identificando o que cada argumento representa. No método de exemplo abaixo, o sellerName não pode ser nulo ou um espaço em branco. Como sellerName e productName são tipos de cadeia de caracteres, em vez de enviar argumentos por posição, é melhor usar argumentos nomeados para remover a ambiguidade dos dois e reduzir a confusão para qualquer pessoa que leia o código.

Os argumentos nomeados, quando usados com argumentos posicionais, são válidos, desde que

  • não sejam seguidos por argumentos posicionais ou,

    PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
    
  • são usados na posição correta. No exemplo a seguir, o parâmetro orderNum está na posição correta, mas não está explicitamente nomeado.

    PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug");
    

Argumentos posicionais que seguem argumentos nomeados fora de ordem são inválidos.

// This generates CS1738: Named argument specifications must appear after all fixed arguments have been specified.
PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");

Exemplo

O código a seguir implementa os exemplos desta seção, juntamente com outros exemplos.

class NamedExample
{
    static void Main(string[] args)
    {
        // The method can be called in the normal way, by using positional arguments.
        PrintOrderDetails("Gift Shop", 31, "Red Mug");

        // Named arguments can be supplied for the parameters in any order.
        PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
        PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);

        // Named arguments mixed with positional arguments are valid
        // as long as they are used in their correct position.
        PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
        PrintOrderDetails(sellerName: "Gift Shop", 31, productName: "Red Mug"); 
        PrintOrderDetails("Gift Shop", orderNum: 31, "Red Mug");

        // However, mixed arguments are invalid if used out-of-order.
        // The following statements will cause a compiler error.
        // PrintOrderDetails(productName: "Red Mug", 31, "Gift Shop");
        // PrintOrderDetails(31, sellerName: "Gift Shop", "Red Mug");
        // PrintOrderDetails(31, "Red Mug", sellerName: "Gift Shop");
    }

    static void PrintOrderDetails(string sellerName, int orderNum, string productName)
    {
        if (string.IsNullOrWhiteSpace(sellerName))
        {
            throw new ArgumentException(message: "Seller name cannot be null or empty.", paramName: nameof(sellerName));
        }

        Console.WriteLine($"Seller: {sellerName}, Order #: {orderNum}, Product: {productName}");
    }
}

Argumentos opcionais

A definição de um método, construtor, indexador ou delegado pode especificar que seus parâmetros são obrigatórios ou opcionais. Qualquer chamada deve fornecer argumentos para todos os parâmetros necessários, mas pode omitir argumentos para parâmetros opcionais.

Cada parâmetro opcional tem um valor padrão como parte de sua definição. Se nenhum argumento é enviado para esse parâmetro, o valor padrão é usado. Um valor padrão deve ser um dos seguintes tipos de expressões:

  • uma expressão de constante;
  • uma expressão da forma new ValType(), em que ValType é um tipo de valor, como um enum ou um struct;
  • uma expressão da forma default(ValType), em que ValType é um tipo de valor.

Os parâmetros opcionais são definidos no final da lista de parâmetros, depois de todos os parâmetros obrigatórios. Se o chamador fornecer um argumento para qualquer um de uma sucessão de parâmetros opcionais, ele deverá fornecer argumentos para todos os parâmetros opcionais anteriores. Não há suporte para intervalos separados por vírgula na lista de argumentos. Por exemplo, no código a seguir, método de instância ExampleMethod está definido com um parâmetro obrigatório e dois opcionais.

public void ExampleMethod(int required, string optionalstr = "default string",
    int optionalint = 10)

A chamada para ExampleMethod a seguir causa um erro do compilador, porque um argumento é fornecido para o terceiro parâmetro, mas não para o segundo.

//anExample.ExampleMethod(3, ,4);

No entanto, se você souber o nome do terceiro parâmetro, poderá usar um argumento nomeado para realizar a tarefa.

anExample.ExampleMethod(3, optionalint: 4);

O IntelliSense usa colchetes para indicar parâmetros opcionais, conforme mostrado na seguinte ilustração:

Captura de tela mostrando as Informações Rápidas do IntelliSense para o método ExampleMethod.

Observação

Você também pode declarar parâmetros opcionais usando a classe OptionalAttribute do .NET. Os parâmetros OptionalAttribute não exigem um valor padrão. No entanto, se um valor padrão for desejado, dê uma olhada na classe DefaultParameterValueAttribute.

Exemplo

No exemplo a seguir, o construtor para ExampleClass tem um parâmetro, que é opcional. O método de instância ExampleMethod tem um parâmetro obrigatório, required e dois parâmetros opcionais, optionalstr e optionalint. O código em Main mostra as diferentes maneiras em que o construtor e o método podem ser invocados.

namespace OptionalNamespace
{
    class OptionalExample
    {
        static void Main(string[] args)
        {
            // Instance anExample does not send an argument for the constructor's
            // optional parameter.
            ExampleClass anExample = new ExampleClass();
            anExample.ExampleMethod(1, "One", 1);
            anExample.ExampleMethod(2, "Two");
            anExample.ExampleMethod(3);

            // Instance anotherExample sends an argument for the constructor's
            // optional parameter.
            ExampleClass anotherExample = new ExampleClass("Provided name");
            anotherExample.ExampleMethod(1, "One", 1);
            anotherExample.ExampleMethod(2, "Two");
            anotherExample.ExampleMethod(3);

            // The following statements produce compiler errors.

            // An argument must be supplied for the first parameter, and it
            // must be an integer.
            //anExample.ExampleMethod("One", 1);
            //anExample.ExampleMethod();

            // You cannot leave a gap in the provided arguments.
            //anExample.ExampleMethod(3, ,4);
            //anExample.ExampleMethod(3, 4);

            // You can use a named parameter to make the previous
            // statement work.
            anExample.ExampleMethod(3, optionalint: 4);
        }
    }

    class ExampleClass
    {
        private string _name;

        // Because the parameter for the constructor, name, has a default
        // value assigned to it, it is optional.
        public ExampleClass(string name = "Default name")
        {
            _name = name;
        }

        // The first parameter, required, has no default value assigned
        // to it. Therefore, it is not optional. Both optionalstr and
        // optionalint have default values assigned to them. They are optional.
        public void ExampleMethod(int required, string optionalstr = "default string",
            int optionalint = 10)
        {
            Console.WriteLine(
                $"{_name}: {required}, {optionalstr}, and {optionalint}.");
        }
    }

    // The output from this example is the following:
    // Default name: 1, One, and 1.
    // Default name: 2, Two, and 10.
    // Default name: 3, default string, and 10.
    // Provided name: 1, One, and 1.
    // Provided name: 2, Two, and 10.
    // Provided name: 3, default string, and 10.
    // Default name: 3, default string, and 4.
}

O código anterior mostra vários exemplos em que os parâmetros opcionais não estão aplicados corretamente. O primeiro ilustra que um argumento deve ser fornecido para o primeiro parâmetro, o que é necessário.

Atributos de informações do chamador

Atributosde informações do chamador, como CallerFilePathAttribute, CallerLineNumberAttribute, CallerMemberNameAttribute e CallerArgumentExpressionAttribute, são usados para obter informações sobre o chamador de um método. Esses atributos são especialmente úteis quando você está depurando ou quando precisa registrar informações sobre chamadas de método.

Esses atributos são parâmetros opcionais com valores padrão fornecidos pelo compilador. O chamador não deve fornecer explicitamente um valor para esses parâmetros.

Interfaces COM

Os argumentos nomeados e opcionais, juntamente com suporte para objetos dinâmicos e outros aprimoramentos, aprimoram enormemente a interoperabilidade com APIs COM, como APIs de Automação do Office.

Por exemplo, o método AutoFormat na interface Range do Microsoft Office Excel tem sete parâmetros, todos opcionais. Esses parâmetros são mostrados na seguinte ilustração:

Captura de tela mostrando as Informações Rápidas do IntelliSense para o método AutoFormat.

No entanto, você pode simplificar muito a chamada para AutoFormat usando argumentos nomeados e opcionais. Os argumentos nomeados e opcionais permitem que você omita o argumento para um parâmetro opcional se não desejar alterar o valor padrão do parâmetro. Na chamada a seguir, um valor é especificado para apenas um dos sete parâmetros.

var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Workbooks.Add();
excelApp.Visible = true;

var myFormat =
    Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatAccounting1;

excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat );

Para obter mais informações e exemplos, consulte Como usar argumentos nomeados e opcionais na programação do Office e Como acessar objetos de interoperabilidade do Office usando recursos do Visual C#.

Resolução de sobrecarga

O uso de argumentos nomeados e opcionais afeta a resolução de sobrecarga das seguintes maneiras:

  • Um método, indexador ou construtor é um candidato para a execução se cada um dos parâmetros é opcional ou corresponde, por nome ou posição, a um único argumento na instrução de chamada e esse argumento pode ser convertido para o tipo do parâmetro.
  • Se mais de um candidato for encontrado, as regras de resolução de sobrecarga de conversões preferenciais serão aplicadas aos argumentos que são especificados explicitamente. Os argumentos omitidos para parâmetros opcionais são ignorados.
  • Se dois candidatos são considerados igualmente bons, a preferência vai para um candidato que não tenha parâmetros opcionais para os quais argumentos foram omitidos na chamada. A resolução de sobrecarga geralmente prefere candidatos com menos parâmetros.

Especificação da linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.