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

Os argumentos nomeados permitem especificar um argumento para um parâmetro combinando o argumento com seu nome em vez de com sua posição na lista de parâmetros. Os argumentos opcionais permitem omitir argumentos para alguns parâmetros. Ambas as técnicas podem ser usadas com 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, não na lista de parâmetros.

Os parâmetros nomeados e opcionais permitem que você forneça argumentos para parâmetros selecionados. Esse recurso facilita muito as chamadas para interfaces COM, como as APIs de automação do Microsoft Office.

Argumentos com nome

Os argumentos nomeados liberam você de fazer a correspondência entre a ordem dos argumentos e a ordem dos parâmetros nas listas de parâmetros dos 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 do pedido (como nome do vendedor, número do pedido e nome do produto) pode ser chamada enviando argumentos por posição, na ordem definida pela função.

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

Se você não se lembra da ordem dos parâmetros, mas sabe seus nomes, você pode 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 seu código, identificando o que cada argumento representa. No método de exemplo abaixo, o sellerName não pode ser nulo ou espaço em branco. Como ambos sellerName são productName tipos de cadeia de caracteres, em vez de enviar argumentos por posição, faz sentido usar argumentos nomeados para desambiguar os dois e reduzir a confusão para quem lê o código.

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

  • eles não são seguidos por quaisquer argumentos posicionais, ou

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

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

Os argumentos posicionais que seguem quaisquer 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 alguns adicionais.

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 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 for enviado para esse parâmetro, o valor padrão será usado. Um valor padrão deve ser um dos seguintes tipos de expressões:

  • uma expressão constante;
  • uma expressão da forma new ValType(), onde ValType é um tipo de valor, como um enum ou um struct;
  • uma expressão do formulário default(ValType), onde ValType é um tipo de valor.

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

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

A chamada a seguir causa ExampleMethod um erro de 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 ilustração a seguir:

Captura de tela mostrando informações rápidas do IntelliSense para o método ExampleMethod.

Nota

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

Exemplo

No exemplo a seguir, o construtor for ExampleClass tem um parâmetro, que é opcional. O método ExampleMethod de instância tem um parâmetro necessário, requirede dois parâmetros opcionais, optionalstr e optionalint. O código em Main mostra as diferentes maneiras pelas quais 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 são aplicados corretamente. O primeiro ilustra que um argumento deve ser fornecido para o primeiro parâmetro, que é necessário.

Atributos de informações do chamador

Os atributos de informações do chamador, como CallerFilePathAttribute, CallerLineNumberAttribute, CallerMemberNameAttribute, e CallerArgumentExpressionAttribute, são usados para obter informações sobre o chamador para 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 o suporte para objetos dinâmicos, melhoram muito a interoperabilidade com APIs COM, como APIs de automação do Office.

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

Captura de tela mostrando informações rápidas do IntelliSense para o método AutoFormatação.

No entanto, você pode simplificar muito a chamada usando AutoFormat argumentos nomeados e opcionais. Os argumentos nomeados e opcionais permitem que você omita o argumento de um parâmetro opcional se não quiser 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 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 execução se cada um de seus parâmetros for opcional ou corresponder, por nome ou por 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 para conversões preferenciais serão aplicadas aos argumentos explicitamente especificados. Os argumentos omitidos para parâmetros opcionais são ignorados.
  • Se dois candidatos forem considerados igualmente bons, a preferência vai para um candidato que não tenha parâmetros opcionais para os quais os argumentos foram omitidos na chamada. A resolução de sobrecarga geralmente prefere candidatos que tenham 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 do C#.