Argomenti denominati e facoltativi (Guida per programmatori C#)

Gli argomenti denominati consentono di specificare un argomento per un parametro associando l'argomento al nome anziché alla relativa posizione nell'elenco dei parametri. Gli argomenti facoltativi consentono di omettere gli argomenti per alcuni parametri. Entrambe le tecniche possono essere usate con i metodi, gli indicizzatori, i costruttori e i delegati.

Quando si usano gli argomenti denominati e facoltativi, gli argomenti vengono valutati nell'ordine nel quale sono visualizzati nell'elenco di argomenti, non nell'elenco di parametri.

I parametri denominati e facoltativi consentono di specificare argomenti per i parametri selezionati. Questa funzionalità semplifica notevolmente le chiamate alle interfacce COM, ad esempio le API di Automazione di Microsoft Office.

Argomenti denominati

Gli argomenti denominati consentono di associare l'ordine degli argomenti all'ordine dei parametri negli elenchi di parametri dei metodi chiamati. L'argomento per ogni parametro può essere specificato in base al nome del parametro. Ad esempio, una funzione che stampa i dettagli dell'ordine (ad esempio, il nome del venditore, il numero di ordine e il nome del prodotto) può essere chiamata inviando argomenti in base alla posizione, nell'ordine definito dalla funzione .

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

Se non si ricorda l'ordine dei parametri ma si conoscono i relativi nomi, è possibile inviare gli argomenti in qualsiasi ordine.

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

Gli argomenti denominati migliorano anche la leggibilità del codice identificando che cosa rappresenta ogni argomento. Nel metodo di esempio seguente, sellerName non può essere null o uno spazio vuoto. sellerName e productName sono di tipi stringa, quindi, anziché inviare argomenti in base alla posizione, è opportuno usare argomenti denominati per evitare ambiguità tra i due e semplificare la lettura del codice.

Se usati con argomenti posizionali, gli argomenti denominati sono validi se

  • non sono seguiti da argomenti posizionali, o

    PrintOrderDetails("Gift Shop", 31, productName: "Red Mug");
    
  • vengono usati nella posizione corretta. Nell'esempio seguente il parametro orderNum è nella posizione corretta, ma non è denominato in modo esplicito.

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

Gli argomenti posizionali che seguono argomenti denominati non ordinati non sono validi.

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

Esempio

Il codice seguente implementa gli esempi di questa e altre sezioni.

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}");
    }
}

Argomenti facoltativi

La definizione di un metodo, un costruttore, un indicizzatore o un delegato può specificare i relativi parametri sono obbligatori o facoltativi. Tutte le chiamate devono specificare gli argomenti per tutti i parametri obbligatori, ma possono omettere gli argomenti per i parametri facoltativi.

Ogni parametro facoltativo ha un valore predefinito incluso nella definizione. Se per il parametro non viene inviato alcun argomento, viene usato il valore predefinito. Il valore predefinito deve essere uno dei tipi di espressioni seguenti:

  • un'espressione costante;
  • un'espressione del form new ValType(), dove ValType è un tipo di valore, ad esempio enum o struct;
  • un'espressione del form default(ValType), dove ValType è un tipo di valore.

I parametri facoltativi sono definiti alla fine dell'elenco di parametri, dopo eventuali parametri obbligatori. Se il chiamante specifica un argomento per un parametro di una successione di parametri facoltativi, deve specificare gli argomenti per tutti i parametri facoltativi precedenti. Le lacune separate da virgole nell'elenco di argomenti non sono supportate. Nel codice seguente, ad esempio, il metodo di istanza ExampleMethod viene definito con un parametro obbligatorio e due parametri facoltativi.

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

La chiamata seguente a ExampleMethod genera un errore del compilatore, poiché viene specificato un argomento per il terzo parametro ma non per il secondo.

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

Se, tuttavia, si conosce il nome del terzo parametro, è possibile usare un argomento denominato per eseguire l'attività.

anExample.ExampleMethod(3, optionalint: 4);

IntelliSense usa le parentesi per indicare parametri facoltativi, come illustrato nell'immagine seguente:

Screenshot con le informazioni rapide di IntelliSense per il metodo ExampleMethod.

Nota

È possibile anche dichiarare parametri facoltativi usando la classe .NET OptionalAttribute. I parametri OptionalAttribute non richiedono un valore predefinito. Tuttavia, se si desidera un valore predefinito, esaminare la DefaultParameterValueAttribute classe .

Esempio

Nell'esempio seguente il costruttore per ExampleClass ha un solo parametro facoltativo. Il metodo di istanza ExampleMethod ha un solo parametro obbligatorio, required, e due parametri facoltativi, optionalstr e optionalint. Il codice in Main illustra i diversi modi in cui è possibile richiamare il costruttore e il metodo.

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.
}

Il codice precedente mostra alcuni esempi in cui i parametri facoltativi non vengono applicati correttamente. Il primo illustra che è necessario specificare un argomento per il primo parametro, obbligatorio.

Attributi delle informazioni sul chiamante

Gli attributi delle informazioni sul chiamante, ad esempio CallerFilePathAttribute, CallerLineNumberAttributeCallerMemberNameAttribute, e CallerArgumentExpressionAttribute, vengono usati per ottenere informazioni sul chiamante a un metodo. Questi attributi sono particolarmente utili quando si esegue il debug o quando è necessario registrare informazioni sulle chiamate al metodo.

Questi attributi sono parametri facoltativi con valori predefiniti forniti dal compilatore. Il chiamante non deve fornire in modo esplicito un valore per questi parametri.

Interfacce COM

Gli argomenti denominati e facoltativi, insieme al supporto per oggetti dinamici, migliorano notevolmente l'interoperabilità con le API COM, ad esempio le API di Automazione di Office.

Ad esempio, il metodo AutoFormat nell'interfaccia Range di Microsoft Office Excel ha sette parametri facoltativi. Questi parametri sono illustrati nell'immagine seguente:

Screenshot con le informazioni rapide di IntelliSense per il metodo AutoFormat.

Tuttavia, è possibile semplificare notevolmente la chiamata a AutoFormat usando argomenti denominati e facoltativi. Gli argomenti denominati e facoltativi consentono di omettere l'argomento per un parametro facoltativo se non si vuole modificare il valore predefinito del parametro. Nella chiamata seguente viene specificato un valore per uno solo dei sette parametri.

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 );

Per altre informazioni ed esempi, vedere Come usare argomenti denominati e facoltativi nella programmazione di Office e Come accedere agli oggetti di interoperabilità di Office usando le funzionalità C#.

Risoluzione dell'overload

L'uso di argomenti denominati e facoltativi influisce sulla risoluzione dell'overload nei modi seguenti:

  • Un metodo, un indicizzatore o un costruttore è un candidato per l'esecuzione se ogni parametro è facoltativo o corrisponde, per nome o per posizione, a un solo argomento nell'istruzione chiamante e tale argomento può essere convertito nel tipo del parametro.
  • Se è disponibile più di un candidato, agli argomenti specificati in modo esplicito vengono applicate le regole di risoluzione dell'overload per le conversioni preferite. Gli argomenti omessi per i parametri facoltativi vengono ignorati.
  • Se due candidati sono giudicati ugualmente validi, la preferenza va a un candidato che non ha parametri facoltativi per i quali sono stati omessi gli argomenti nella chiamata. La risoluzione dell'overload in genere preferisce candidati con meno parametri.

Specifiche del linguaggio C#

Per altre informazioni, vedere la specifica del linguaggio C#. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.