Specificare argomenti di metodo denominati e facoltativi

Completato

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 argomenti per alcuni parametri. Entrambe le tecniche possono essere usate con metodi, indicizzatori, costruttori e delegati.

Quando si usano argomenti denominati e facoltativi, gli argomenti vengono valutati nell'ordine in cui vengono visualizzati nell'elenco di argomenti, non nell'elenco dei 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.

Nota

Gli argomenti denominati migliorano la leggibilità del codice identificando ciò che ogni argomento rappresenta.

Si consideri un metodo che usa la firma del metodo seguente:


static void PrintOrderDetails(string sellerName, int orderNum, string productName)
{
    // Code to print the order details
}

Questo metodo può essere chiamato correttamente senza usare argomenti denominati, purché gli argomenti siano nell'ordine corretto (definito dalla firma del metodo):


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

Se usato con argomenti posizionali, gli argomenti denominati sono validi purché vengano usati nella posizione corretta.

L'esempio seguente funziona correttamente perché il parametro productName è denominato in modo esplicito, non è seguito da alcun argomento posizionale e si trova nella posizione corretta.


PrintOrderDetails("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");

Argomenti facoltativi

Una definizione di metodo può specificare se i parametri sono obbligatori o facoltativi. Qualsiasi chiamata deve fornire argomenti per tutti i parametri obbligatori, ma può omettere argomenti per i parametri facoltativi. Un tipo riferimento nullable (T?) consente agli argomenti di essere esplicitamente null, ma non rende intrinsecamente facoltativo un parametro.

Ogni parametro facoltativo ha un valore predefinito come parte della relativa definizione. Se non viene inviato alcun argomento per tale parametro, viene usato il valore predefinito. Un valore predefinito deve essere uno dei tipi di espressioni seguenti:

  • Espressione costante, ad esempio una stringa letterale o un numero.
  • Espressione del form new ValType(), dove ValType è un tipo valore, ad esempio un enum o un struct.
  • Espressione del form default(ValType), dove ValType è un tipo valore.

I parametri facoltativi vengono definiti alla fine dell'elenco di parametri, dopo tutti i parametri obbligatori. Il chiamante deve fornire argomenti per tutti i parametri obbligatori ed eventuali parametri facoltativi precedenti a quelli specificati. 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 uno obbligatorio e due parametri facoltativi.


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

La chiamata seguente a ExampleMethod causa un errore del compilatore, perché viene fornito un argomento per il terzo parametro ma non per il secondo.


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

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


anExample.ExampleMethod(3, optionalint: 4);

IntelliSense usa parentesi quadre per indicare parametri facoltativi, come illustrato nella figura seguente:

Screenshot che mostra in che modo IntelliSence usa le parentesi quadre per indicare parametri facoltativi.

Nota

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

Nell'esempio seguente il costruttore per ExampleClass ha un parametro, che è facoltativo. Il metodo di istanza ExampleMethod ha un parametro obbligatorio, requirede due parametri facoltativi, optionalstr e optionalint. Il codice in Main mostra 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 can't 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's optional.
        public ExampleClass(string name = "Default name")
        {
            _name = name;
        }

        // The first parameter, required, has no default value assigned
        // to it. Therefore, it isn't optional. Both optionalstr and
        // optionalint have default values assigned to them. They're 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.
}

Risoluzione dell'overload per argomenti denominati e facoltativi

I metodi di overload sono metodi con lo stesso nome ma firme diverse. La firma di un metodo è costituita dal nome del metodo e dal tipo e dal tipo (valore, riferimento o output) di ognuno dei relativi parametri formali. La risoluzione dell'overload è il processo di selezione del metodo migliore da chiamare tra diversi metodi con lo stesso nome ma firme diverse.

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

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