parameter - ¿Cómo puedes usar parámetros opcionales en C#?
optional parameter in c# (19)
Hola mundo opcional
Si desea que el tiempo de ejecución proporcione un valor de parámetro predeterminado, debe utilizar la reflexión para realizar la llamada. No es tan agradable como las otras sugerencias para esta pregunta, pero es 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 });
}
}
}
Nota: esta pregunta se hizo en un momento en que C # aún no admite parámetros opcionales (es decir, antes de C # 4).
Estamos creando una API web que se genera mediante programación a partir de una clase C #. La clase tiene el método GetFooBar(int a, int b)
y la API tiene un método GetFooBar
tomando GetFooBar
consulta como &a=foo &b=bar
.
Las clases deben admitir parámetros opcionales, que no se admiten en C # el idioma. ¿Cuál es el mejor enfoque?
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 contenedor de API, detectamos parámetros opcionales (ParameterInfo p.IsOptional) y establecemos un valor predeterminado. El objetivo es marcar los parámetros como opcionales sin tener que recurrir a kludges como tener "opcional" en el nombre del parámetro.
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 ERA 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 admite 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
}
En lugar de los parámetros predeterminados, ¿por qué no construir una clase de diccionario a partir de la cadena de consulta aprobada? Una implementación que es casi idéntica a la forma en que los formularios asp.net funcionan con las cadenas de consulta.
es decir, Request.QueryString ["a"]
Esto desacoplará la clase de hoja del código de fábrica / repetitivo.
También es posible que desee revisar los servicios web con ASP.NET . Los servicios web son una API web que se genera automáticamente a través de los atributos en las clases de C #.
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 método web, que usar varias versiones del mismo método. Creo que en esta situación, los tipos anulables 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
}
}
La forma típica en que esto se maneja en C # como se menciona en stephen es sobrecargar el método. Al crear múltiples versiones del método con diferentes parámetros, usted crea efectivamente parámetros opcionales. En los formularios con menos parámetros, normalmente llamaría la forma del método con todos los parámetros que configuran sus valores predeterminados en la llamada a ese método.
Los parámetros opcionales no son más que parámetros por defecto! Le sugiero que les dé a ambos parámetros por defecto. 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 , el valor pasado para a, 0 y si pasa 2 valores, primero se asignará a ay segundo a b.
Espero que responda a tu pregunta.
Los parámetros opcionales son para los 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. Aquí hay 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 } }
utilizando las versiones de c # anteriores a c # 4.0: debe usar el encadenamiento de constructores (usando la palabra clave:), donde los constructores más simples llevan a un "constructor maestro". 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 } }
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);
Podrías usar el método de sobrecarga ...
GetFooBar() GetFooBar(int a) GetFooBar(int a, int b)
Depende de las firmas del método, al ejemplo que dí le falta el único método "int b" porque tendría la misma firma que el método "int a".
Podrías usar tipos de Nullable ...
GetFooBar(int? a, int? b)
Luego puede verificar, usando a.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 quisieras ir con parámetros con nombre, tendrías que crear un tipo para manejarlos, aunque creo que ya hay algo como esto para las aplicaciones web.
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 de devolución de llamada opcional:
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;
}
Puede utilizar parámetros opcionales en C # 4.0 sin ninguna preocupación. 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 función llamada "parámetros nombrados", puede pasar parámetros por sus nombres y, por supuesto, puede pasar parámetros en el orden que desee :)
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 }
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)
Sorprendido, nadie mencionó 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 aún ocupa el puesto # 1 en Google por "argumentos opcionales de C #", así que pensé: vale la pena estar aquí. Lo siento.
Tengo un servicio web para escribir que lleva 7 parámetros. Cada uno es un atributo de consulta opcional para una declaración SQL envuelta por este servicio web. Entonces, se me ocurren dos soluciones alternativas a los parámetros no opcionales ... ambos bastante pobres:
metodo 1 (param1, param2, param 3, param 4, param 5, param 6, param7) metodo 1 (param1, param2, param3, param 4, param5, param 6) metodo 1 (param1, param2, param3, param4, param5, param7 ) ... empieza a ver la foto. Así miente la locura. Demasiadas combinaciones.
Ahora, para una forma más simple que se ve 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 hack, pero funcionará.
Tuve que hacer esto en un servicio web VB.Net 2.0. Terminé especificando los parámetros como cadenas, luego convirtiéndolos a lo que fuera necesario. 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 capturar todas las excepciones que pueden ocurrir.
Un poco tarde para la fiesta, pero estaba buscando la respuesta a esta pregunta y, finalmente, descubrí otra forma de hacerlo. Declare los tipos de datos para los argumentos opcionales de su método web como tipo XmlNode. Si se omite el argumento opcional, esto se establecerá en nulo, y si está presente, puede obtener su valor de cadena llamando a arg.Value, 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 en .NET para el ws todavía muestra la lista de argumentos (aunque usted pierde los cuadros de entrada de texto útiles para la prueba).
Una manera elegante y fácil que le permite omitir cualquier parámetro en cualquier posición , aprovechando los tipos de nulos es el 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 anulables 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 desea al nombrarlos . Consulte el siguiente enlace para obtener más información sobre los parámetros nombrados y opcionales:
Argumentos con nombre y opcionales (Guía de programación de C #) @ MSDN