¿Cómo se pueden utilizar parámetros opcionales en C#?


Nota: Esta pregunta se hizo en un momento en que C# todavía no soportaba parámetros opcionales (es decir, antes de C# 4).

Estamos construyendo una API web que se genera mediante programación a partir de una clase C#. La clase tiene método GetFooBar(int a, int b) y la API tiene un método GetFooBar tomando parámetros de consulta como &a=foo &b=bar.

Las clases necesitan soportar parámetros opcionales, lo cual no es soportado en C# el lenguaje. ¿Cuál es el mejor enfoque?

Author: Julian, 2008-10-14

19 answers

Sorprendido de que nadie mencionara los parámetros opcionales de C # 4.0 que funcionan así:

public void SomeMethod(int a, int b = 0)
{
   //some code
}

Edit: Sé que en el momento en que se hizo la pregunta, C# 4.0 no existía. Pero esta pregunta todavía ocupa el puesto # 1 en Google para " argumentos opcionales de C#", así que pensé: esta respuesta vale la pena estar aquí. Disculpe....

 895
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-07 15:17:22

Otra opción es usar la palabra clave params

public void DoSomething(params object[] theObjects)
{
  foreach(object o in theObjects)
  {
    // Something with the Objects…
  }
}

Llamado como...

DoSomething(this, that, theOther);
 116
Author: Tim Jarvis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-30 05:06:39

En C#, normalmente usaría múltiples formas del método:

void GetFooBar(int a) { int defaultBValue;  GetFooBar(a, defaultBValue); }
void GetFooBar(int a, int b)
{
 // whatever here
}

ACTUALIZACIÓN: Esto mencionado anteriormente fue la forma en que hice los valores predeterminados con C# 2.0. Los proyectos en los que estoy trabajando ahora están usando C# 4.0 que ahora soporta directamente parámetros opcionales. Aquí hay un ejemplo que acabo de usar en mi propio código:

public EDIDocument ApplyEDIEnvelop(EDIVanInfo sender, 
                                   EDIVanInfo receiver, 
                                   EDIDocumentInfo info,
                                   EDIDocumentType type 
                                     = new EDIDocumentType(EDIDocTypes.X12_814),
                                   bool Production = false)
{
   // My code is here
}
 70
Author: stephenbayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-01 16:53:27

Desde este sitio:

Http://www.tek-tips.com/viewthread.cfm?qid=1500861&page=1

C# permite el uso del atributo [Opcional] (de VB, aunque no es funcional en C#). Así que puedes tener un método como este:

using System.Runtime.InteropServices;
public void Foo(int a, int b, [Optional] int c)
{
  ...
}

En nuestro envoltorio API, detectamos parámetros opcionales (ParameterInfo p. IsOptional) y establecemos un valor predeterminado. El objetivo es marcar los parámetros como opcionales sin recurrir a kludges como tener "opcional" en el nombre del parámetro.

 40
Author: Kalid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 01:57:23

Se podría utilizar el método de sobrecarga...

GetFooBar()
GetFooBar(int a)
GetFooBar(int a, int b)

Depende de las firmas del método, al ejemplo que di le falta el método "int b" solamente porque tendría la misma firma que el método "int a".

Puedes usar tipos Nullables...

GetFooBar(int? a, int? b)

A continuación, puede comprobar, utilizando un.HasValue, para ver si se ha establecido un parámetro.

Otra opción sería usar un parámetro 'params'.

GetFooBar(params object[] args)

Si usted quisiera ir con los parámetros nombrados necesitaría cree un tipo para manejarlos, aunque creo que ya hay algo como esto para las aplicaciones web.

 21
Author: Kepboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-06 13:48:44

Puede usar parámetros opcionales en C# 4.0 sin preocupaciones. Si tenemos un método como:

int MyMetod(int param1, int param2, int param3=10, int param4=20){....}

Cuando llama al método, puede omitir parámetros como este:

int variab = MyMethod(param3:50; param1:10);

C # 4.0 implementa una característica llamada "parámetros con nombre", en realidad puede pasar parámetros por sus nombres, y por supuesto puede pasar parámetros en el orden que desee :)

 18
Author: kristi_io,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-02 14:19:41

Hola Mundo opcional

Si desea que el tiempo de ejecución proporcione un valor de parámetro predeterminado, debe usar reflexión para realizar la llamada. No tan agradable como las otras sugerencias para esta pregunta, pero compatible con VB.NET.

using System;
using System.Runtime.InteropServices;
using System.Reflection;

namespace ConsoleApplication1
{
    class Class1
    {
        public static void sayHelloTo(
            [Optional,
            DefaultParameterValue("world")] string whom)
        {
            Console.WriteLine("Hello " + whom);
        }

        [STAThread]
        static void Main(string[] args)
        {
            MethodInfo mi = typeof(Class1).GetMethod("sayHelloTo");
            mi.Invoke(null, new Object[] { Missing.Value });
        }
    }
}
 17
Author: Hugh Allen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 10:58:22

Una manera elegante y fácil que le permite omitir cualquier parámetro en cualquier posición, aprovechando tipos nullables es la siguiente:

public void PrintValues(int? a = null, int? b = null, float? c = null, string s = "")
{
    if(a.HasValue)
        Console.Write(a);
    else
        Console.Write("-");

    if(b.HasValue)
        Console.Write(b);
    else
        Console.Write("-");

    if(c.HasValue)
        Console.Write(c);
    else
        Console.Write("-");

    if(string.IsNullOrEmpty(s)) // Different check for strings
        Console.Write(s);
    else
        Console.Write("-");
}

Las cadenas ya son tipos nullables, por lo que no necesitan el ?.

Una vez que tenga este método, las siguientes llamadas son todas válidas:

PrintValues (1, 2, 2.2f);
PrintValues (1, c: 1.2f);
PrintValues(b:100);
PrintValues (c: 1.2f, s: "hello");
PrintValues();

Cuando define un método de esa manera, tiene la libertad de establecer solo los parámetros que desee al nombrarlos . Consulte el siguiente enlace para obtener más información sobre parámetros con nombre y opcionales:

Argumentos con nombre y Opcionales (Guía de Programación en C#) @ MSDN

 8
Author: SteakOverflow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-29 11:58:44

Estoy de acuerdo con Stephenbayer. Pero como es un servicio web, es más fácil para el usuario final usar solo una forma del webmethod, que usar varias versiones del mismo método. Creo que en esta situación los tipos Nullables son perfectos para parámetros opcionales.

public void Foo(int a, int b, int? c)
{
  if(c.HasValue)
  {
    // do something with a,b and c
  }
  else
  {
    // do something with a and b only
  }  
}
 7
Author: Vivek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 02:14:34

Los parámetros opcionales son para métodos. si necesita argumentos opcionales para una clase y usted es:

  • Usando c# 4.0: use argumentos opcionales en el constructor de la clase, una solución que prefiero, ya que está más cerca de lo que se hace con los métodos, por lo que es más fácil de recordar. he aquí un ejemplo:

    class myClass
    {
        public myClass(int myInt = 1, string myString =
                               "wow, this is cool: i can have a default string")
        {
            // do something here if needed
        }
    }
    
  • Usando versiones de c# anteriores a c # 4.0: debe usar el encadenamiento de constructores (usando la palabra clave: this), donde los constructores más simples conducen a un " maestro constructor". ejemplo:

    class myClass
    {
        public myClass()
        {
        // this is the default constructor
        }
    
        public myClass(int myInt)
            : this(myInt, "whatever")
        {
            // do something here if needed
        }
        public myClass(string myString)
            : this(0, myString)
        {
            // do something here if needed
        }
        public myClass(int myInt, string myString)
        {
            // do something here if needed - this is the master constructor
        }
    }
    
 6
Author: baskinhu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-12 14:20:53

La forma típica de manejar esto en C# como Stephen mencionó es sobrecargar el método. Al crear varias versiones del método con diferentes parámetros, puede crear parámetros opcionales de manera efectiva. En los formularios con menos parámetros, normalmente llamaría a la forma del método con todos los parámetros configurando sus valores predeterminados en la llamada a ese método.

 2
Author: cfbarbero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 02:03:53

Puedes sobrecargar tu método. Un método contiene un parámetro GetFooBar(int a) y el otro contiene ambos parámetros, GetFooBar(int a, int b)

 1
Author: user2933082,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-08 03:18:07

En lugar de los parámetros predeterminados, ¿por qué no construir una clase de diccionario a partir de la cadena de consultas pasada?. una implementación que es casi idéntica a la forma asp.net los formularios funcionan con anillos de consulta.

Es decir, Solicitud.QueryString ["a"]

Esto desacoplará la clase leaf del código factory / boilerplate.


Es posible que también desee comprobar hacia fuera Servicios web con ASP.NET . Los servicios web son una api web generada automáticamente a través de atributos en C# clase.

 0
Author: Robert Paulson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 02:09:07

Un poco tarde a la fiesta, pero estaba buscando la respuesta a esta pregunta y, finalmente, descubrió otra manera de hacer esto. Declare los tipos de datos para los args opcionales de su método web como tipo XmlNode. Si el arg opcional se omite, se establecerá en null, y si está presente, puede obtener el valor de cadena llamando a arg.Valor, es decir,

[WebMethod]
public string Foo(string arg1, XmlNode optarg2)
{
    string arg2 = "";
    if (optarg2 != null)
    {
        arg2 = optarg2.Value;
    }
    ... etc
}

Lo que también es decente acerca de este enfoque es que la página de inicio generada por. NET para el ws todavía muestra la lista de argumentos (aunque usted pierde los prácticos cuadros de entrada de texto para probar).

 0
Author: Ron K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-17 01:50:33

Tengo un servicio web para escribir que toma 7 parámetros. Cada uno es un atributo de consulta opcional para una instrucción sql empaquetada por este servicio web. Así que dos soluciones a los parámetros no opcionales vienen a la mente... ambos bastante pobres:

Method1 (param1, param2, param 3, param 4, param 5, param 6, param7) método 1 (param1, param2, param3, parámetro 4, param5, parámetro 6) método 1 (param1, param2, param3, param4, param5, param7)... empieza a ver la imagen. Así es la locura. Demasiados combinado.

Ahora una forma más simple que parece incómoda pero debería funcionar: method1 (param1, bool useParam1, param2, bool useParam2, etc...)

Esa es una llamada al método, se requieren valores para todos los parámetros, y manejará cada caso dentro de él. También está claro cómo usarlo desde la interfaz.

Es un truco, pero funcionará.

 0
Author: Spanky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-22 00:40:52

Tuve que hacer esto en un VB.Net 2.0 Servicio Web. Terminé especificando los parámetros como cadenas, luego los convertí a lo que necesitaba. Se especificó un parámetro opcional con una cadena vacía. No es la solución más limpia, pero funcionó. Solo tenga cuidado de que usted captura todas las excepciones que pueden ocurrir.

 0
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-03 20:21:22

Por si acaso si alguien quiere pasar una devolución de llamada (o delegate) como un parámetro opcional, puede hacerlo de esta manera.

Parámetro opcional de devolución de llamada:

public static bool IsOnlyOneElement(this IList lst, Action callbackOnTrue = (Action)((null)), Action callbackOnFalse = (Action)((null)))
{
    var isOnlyOne = lst.Count == 1;
    if (isOnlyOne && callbackOnTrue != null) callbackOnTrue();
    if (!isOnlyOne && callbackOnFalse != null) callbackOnFalse();
    return isOnlyOne;
}
 0
Author: CodeArtist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-17 13:46:48

Los parámetros opcionales no son más que parámetros predeterminados! sugiero que les des a ambos parámetros predeterminados. GetFooBar(int a=0, int b=0) si no tiene ningún método sobrecargado, resultará en a = 0, b = 0 si no pasa ningún valor, si pasa 1 valor, resultará en, valor pasado para a, 0 y si pasa 2 valores 1st se asignará a a y segundo a b.

Espero que eso responda a tu pregunta.

 0
Author: user3555836,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-02 19:54:35

Puedes probar esto también
Tipo 1
public void YourMethod(int a=0, int b = 0) { //some code }


Tipo 2
public void YourMethod(int? a, int? b) { //some code }

 -2
Author: Ankit Panwar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-23 04:30:48