Especificar argumentos de método con nombre y opcionales

Completado

Los argumentos con nombre permiten especificar un argumento para un parámetro haciendo coincidir el argumento con su nombre en lugar de con su posición en la lista de parámetros. Los argumentos opcionales permiten omitir argumentos para algunos parámetros. Ambas técnicas se pueden usar con métodos, indexadores, constructores y delegados.

Cuando se usan argumentos con nombre y opcionales, los argumentos se evalúan en el orden en que aparecen en la lista de argumentos, no en la lista de parámetros.

Los parámetros con nombre y opcionales permiten proporcionar argumentos para los parámetros seleccionados. Esta funcionalidad facilita considerablemente las llamadas a interfaces COM, como las API de Automatización de Microsoft Office.

Argumentos con nombre

Los argumentos con nombre le liberan de hacer coincidir el orden de los argumentos con el orden de los parámetros en las listas de parámetros de los métodos llamados. El argumento de cada parámetro se puede especificar por nombre de parámetro.

Nota

Los argumentos con nombre mejoran la legibilidad del código mediante la identificación de lo que representa cada argumento.

Considere un método que use la siguiente firma de método:


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

Este método se puede llamar correctamente sin usar argumentos con nombre siempre que los argumentos estén en el orden correcto (definido por la firma del método):


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

Si no recuerda el orden de los parámetros, pero conoce sus nombres, puede enviar los argumentos en cualquier orden.


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

Cuando se usa con argumentos posicionales, los argumentos con nombre son válidos siempre que se usen en la posición correcta.

El ejemplo siguiente funciona correctamente porque: el parámetro productName se denomina explícitamente, no va seguido de ningún argumento posicional y está en la posición correcta.


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

Los argumentos posicionales que siguen los argumentos con nombre desordenados no son válidos.


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

Argumentos opcionales

Una definición de método puede especificar si sus parámetros son obligatorios o opcionales. Cualquier llamada debe proporcionar argumentos para todos los parámetros necesarios, pero puede omitir argumentos para parámetros opcionales. Un tipo de referencia que acepta valores NULL (T?) permite que los argumentos se null explícitamente, pero no hacen inherentemente un parámetro opcional.

Cada parámetro opcional tiene un valor predeterminado como parte de su definición. Si no se envía ningún argumento para ese parámetro, se usa el valor predeterminado. Un valor predeterminado debe ser uno de los siguientes tipos de expresiones:

  • Expresión constante, como una cadena literal o un número.
  • Expresión del formulario new ValType(), donde ValType es un tipo de valor, como un enum o un struct.
  • Expresión del formulario default(ValType), donde ValType es un tipo de valor.

Los parámetros opcionales se definen al final de la lista de parámetros, después de los parámetros necesarios. El autor de la llamada debe proporcionar argumentos para todos los parámetros necesarios y los parámetros opcionales anteriores a los especificados. No se admiten espacios separados por comas en la lista de argumentos. Por ejemplo, en el código siguiente, el método de instancia ExampleMethod se define con un parámetro obligatorio y dos parámetros opcionales.


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

La siguiente llamada a ExampleMethod produce un error del compilador, ya que se proporciona un argumento para el tercer parámetro, pero no para el segundo.


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

Sin embargo, si conoce el nombre del tercer parámetro, puede usar un argumento con nombre para realizar la tarea.


anExample.ExampleMethod(3, optionalint: 4);

IntelliSense usa corchetes para indicar parámetros opcionales, como se muestra en la ilustración siguiente:

Captura de pantalla que muestra cómo IntelliSence usa corchetes para indicar parámetros opcionales.

Nota

También puede declarar parámetros opcionales mediante la clase OptionalAttribute de .NET. OptionalAttribute parámetros no requieren un valor predeterminado. Sin embargo, si se desea un valor predeterminado, considere la posibilidad de usar la clase DefaultParameterValueAttribute.

En el ejemplo siguiente, el constructor de ExampleClass tiene un parámetro, que es opcional. El método de instancia ExampleMethod tiene un parámetro necesario, requiredy dos parámetros opcionales, optionalstr y optionalint. El código de Main muestra las distintas formas en que se puede invocar el constructor y el método.


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

Resolución de sobrecarga para argumentos con nombre y opcionales

Los métodos sobrecargados son métodos que tienen el mismo nombre pero firmas diferentes. La firma de un método consta del nombre del método y del tipo y el tipo (valor, referencia o salida) de cada uno de sus parámetros formales. La resolución de sobrecarga es el proceso de seleccionar el mejor método para llamar entre varios métodos que tienen el mismo nombre pero firmas diferentes.

El uso de argumentos con nombre y opcionales afecta a la resolución de sobrecarga de las maneras siguientes:

  • Un método es un candidato para su ejecución si cada uno de sus parámetros es opcional o corresponde, por nombre o por posición, a un único argumento de la instrucción de llamada y ese argumento se puede convertir al tipo del parámetro.
  • Si se encuentra más de un candidato, las reglas de resolución de sobrecarga para las conversiones preferidas se aplican a los argumentos que se especifican explícitamente. Los argumentos omitidos para los parámetros opcionales se omiten.
  • Si se considera que dos candidatos son igualmente buenos, la preferencia va a un candidato que no tiene parámetros opcionales para los que se omiten los argumentos en la llamada. Por lo general, la resolución de sobrecarga prefiere candidatos que tengan menos parámetros.