Argumentos opcionales y con nombre (Guía de programación de C#)

Visual C# 2010 presenta los argumentos opcionales y con nombre. Los argumentos con nombre permiten especificar un argumento para un parámetro determinado mediante la asociación del argumento al nombre del parámetro, no a la posición de este en la lista de parámetros. Los argumentos opcionales permiten omitir argumentos para algunos parámetros. Ambas técnicas se pueden usar con los métodos, indizadores, constructores y delegados.

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

El uso conjunto de los parámetros opcionales y con nombre permite proporcionar argumentos solamente para unos cuantos parámetros de una lista de parámetros opcionales. Esta capacidad facilita enormemente las llamadas a las interfaces COM, como las API de automatización de Microsoft Office.

Argumentos con nombre

Los argumentos con nombre le liberan de la necesidad de recordar o buscar el orden de los parámetros en las listas correspondientes de los métodos a los que se ha llamado. El parámetro de cada argumento se puede especificar mediante el nombre del parámetro. Por ejemplo, se puede llamar a una función que calcula el índice de masa corporal (IMC) de la manera estándar, mediante el envío de argumentos para el peso y el alto por posición, en el orden definido por la función.

CalculateBMI(123, 64);

Si no recuerda el orden de los parámetros pero conoce sus nombres, puede enviar los argumentos en cualquier orden: el peso o el alto en primer lugar indistintamente.

CalculateBMI(weight: 123, height: 64);

CalculateBMI(height: 64, weight: 123);

Los argumentos con nombre también mejoran la legibilidad del código al identificar qué representa cada argumento.

Un argumento con nombre puede aparecer después de los argumentos posicionales, como se muestra aquí.

CalculateBMI(123, height: 64);

Sin embargo, un argumento posicional no puede ir después de un argumento con nombre. La siguiente instrucción produce un error del compilador.

//CalculateBMI(weight: 123, 64);

Ejemplo

El código siguiente implementa los ejemplos de esta sección.

class NamedExample
{
    static void Main(string[] args)
    {
        // The method can be called in the normal way, by using positional arguments.
        Console.WriteLine(CalculateBMI(123, 64));

        // Named arguments can be supplied for the parameters in either order.
        Console.WriteLine(CalculateBMI(weight: 123, height: 64));
        Console.WriteLine(CalculateBMI(height: 64, weight: 123));

        // Positional arguments cannot follow named arguments.
        // The following statement causes a compiler error.
        //Console.WriteLine(CalculateBMI(weight: 123, 64));

        // Named arguments can follow positional arguments.
        Console.WriteLine(CalculateBMI(123, height: 64));
    }

    static int CalculateBMI(int weight, int height)
    {
        return (weight * 703) / (height * height);
    }
}

Argumentos opcionales

En la definición de un método, constructor, indizador o delegado se puede especificar si sus parámetros son obligatorios u opcionales. Todas las llamadas deben proporcionar argumentos para todos los parámetros obligatorios, pero pueden omitir los argumentos para los parámetros opcionales.

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 utiliza el valor predeterminado. Los valores predeterminados deben ser constantes.

Los parámetros opcionales se definen al final de la lista de parámetros, después de los parámetros obligatorios. Si el llamador proporciona un argumento para cualquiera de los parámetros opcionales de una sucesión de este tipo, debe proporcionar argumentos para todos los parámetros opcionales anteriores. No se admiten los espacios separados por comas en la lista de argumentos. Por ejemplo, en el siguiente código, se define el método de instancia ExampleMethod 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 genera un error del compilador, porque se ha proporcionado 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 los parámetros opcionales, tal y como se muestra en la siguiente ilustración.

Parámetros opcionales de ExampleMethod

Información rápida de IntelliSense para el método ExampleMethod.

Nota

También puede declarar parámetros opcionales mediante la clase OptionalAttribute de .NET. Los parámetros OptionalAttribute no requieren un valor predeterminado.

Ejemplo

En el ejemplo siguiente, el constructor para ExampleClass tiene un parámetro, que es opcional. El método de instancia ExampleMethod tiene un parámetro obligatorio, required, y dos parámetros opcionales, optionalstr y optionalint. El código en Main muestra las distintas formas en que se pueden 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 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("{0}: {1}, {2}, and {3}.", _name, required, optionalstr,
                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.

}

Interfaces COM

Los argumentos opcionales y con nombre, así como la compatibilidad con los objetos dinámicos y otros avances, mejoran considerablemente la interoperabilidad con las API de COM, como las API de automatización de Office.

Por ejemplo, el método AutoFormat de la interfaz Range de Microsoft Office Excel tiene siete parámetros, todos ellos opcionales. Estos parámetros se muestran en la siguiente ilustración.

Parámetros de AutoFormat

Información rápida de IntelliSense para el método AutoFormat.

En C# 3.0 y versiones anteriores, se requiere un argumento para cada parámetro, tal y como se muestra en el siguiente ejemplo.

// In C# 3.0 and earlier versions, you need to supply an argument for
// every parameter. The following call specifies a value for the first
// parameter, and sends a placeholder value for the other six. The
// default values are used for those parameters.
var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Workbooks.Add();
excelApp.Visible = true;

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

excelApp.get_Range("A1", "B4").AutoFormat(myFormat, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

Sin embargo, se puede simplificar considerablemente la llamada a AutoFormat utilizando argumentos con nombre y argumentos opcionales, los cuales se incluyen en C# 4.0. Los parámetros opcionales y con nombre permiten omitir el argumento de un parámetro opcional si no se desea cambiar el valor predeterminado del parámetro. En la siguiente llamada, se especifica un valor solamente para uno de los siete parámetros.

// The following code shows the same call to AutoFormat in C# 4.0. Only
// the argument for which you want to provide a specific value is listed.
excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat );

Para obtener más información y ejemplos, vea Cómo: Usar argumentos opcionales y con nombre en la programación de Office (Guía de programación de C#) y Cómo: Tener acceso a objetos de interoperabilidad de Office mediante las características de Visual C# 2010 (Guía de programación de C#).

Resolución de sobrecargas

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

  • Un método, indizador o constructor es candidato para la ejecución si cada uno de sus parámetros es opcional o se corresponde, por nombre o posición, con un argumento único de la instrucción de llamada, y dicho argumento se puede convertir en el tipo del parámetro.

  • Si se encuentra más de un candidato, se aplican reglas de resolución de sobrecarga en relación con las conversiones preferidas a los argumentos especificados explícitamente. Los argumentos omitidos para los parámetros opcionales se pasan por alto.

  • Si dos candidatos se consideran igualmente buenos, la preferencia recae sobre el candidato que no tiene parámetros opcionales para los que se omitieron argumentos en la llamada. Esto es consecuencia de una preferencia general en la resolución de sobrecarga por los candidatos con menos parámetros.

Especificación del lenguaje C#

Para obtener más información, vea la Especificación del lenguaje C#. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.

Vea también

Tareas

Cómo: Usar argumentos opcionales y con nombre en la programación de Office (Guía de programación de C#)

Referencia

Utilizar constructores (Guía de programación de C#)

Utilizar indizadores (Guía de programación de C#)

Otros recursos

Uso de tipo dinámico (Guía de programación de C#)