Comment Pouvez-vous utiliser des paramètres optionnels en C#?
Note: cette question a été posée à un moment où C# ne supportait pas encore les paramètres optionnels (c'est-à-dire avant C# 4).
Nous construisons une API web générée par programmation À partir d'une Classe C#. La classe A la méthode GetFooBar(int a, int b)
et L'API a une méthode GetFooBar
prenant des paramètres de requête comme &a=foo &b=bar
.
Les classes doivent prendre en charge les paramètres facultatifs, qui ne sont pas pris en charge en C# la langue. Quelle est la meilleure approche?
19 réponses
Surpris personne n'a mentionné les paramètres optionnels c # 4.0 qui fonctionnent comme ceci:
public void SomeMethod(int a, int b = 0)
{
//some code
}
Edit: je sais qu'au moment où la question a été posée, C # 4.0 n'existait pas. Mais cette question se classe toujours #1 dans Google pour "C # arguments optionnels" donc j'ai pensé-cette réponse vaut la peine d'être ici. Désolé.
Une autre option consiste à utiliser le mot-clé params
public void DoSomething(params object[] theObjects)
{
foreach(object o in theObjects)
{
// Something with the Objects…
}
}
Appelé comme...
DoSomething(this, that, theOther);
En C#, j'utiliserais normalement plusieurs formes de la méthode:
void GetFooBar(int a) { int defaultBValue; GetFooBar(a, defaultBValue); }
void GetFooBar(int a, int b)
{
// whatever here
}
UPDATE: ceci mentionné ci-dessus était la façon dont j'ai fait des valeurs par défaut avec C# 2.0. Les projets sur lesquels je travaille maintenant utilisent C # 4.0 qui prend désormais directement en charge les paramètres optionnels. Voici un exemple que je viens d'utiliser dans mon propre code:
public EDIDocument ApplyEDIEnvelop(EDIVanInfo sender,
EDIVanInfo receiver,
EDIDocumentInfo info,
EDIDocumentType type
= new EDIDocumentType(EDIDocTypes.X12_814),
bool Production = false)
{
// My code is here
}
À partir de ce site:
Http://www.tek-tips.com/viewthread.cfm?qid=1500861&page=1
C # permet l'utilisation de l'attribut [optionnel] (de VB, mais pas fonctionnel en C#). Donc, vous pouvez avoir une méthode comme celle-ci:
using System.Runtime.InteropServices;
public void Foo(int a, int b, [Optional] int c)
{
...
}
Dans notre wrapper API, nous détectons les paramètres optionnels (ParameterInfo P. IsOptional) et définissons une valeur par défaut. Le but est de marquer les paramètres comme facultatifs sans avoir recours à des kludges comme avoir "facultatif" dans le nom du paramètre.
Vous pouvez utiliser la surcharge de méthode...
GetFooBar() GetFooBar(int a) GetFooBar(int a, int b)
Cela dépend des signatures de méthode, l'exemple que j'ai donné manque la seule méthode "int b" car elle aurait la même signature que la méthode "int a".
Vous pouvez utiliser des types Nullable...
GetFooBar(int? a, int? b)
Vous pouvez ensuite vérifier, en utilisant un. HasValue, si un paramètre a été défini.
Une Autre option serait d'utiliser un 'params' paramètre.
GetFooBar(params object[] args)
Si vous vouliez aller avec des paramètres nommés, vous auriez besoin de créez un type pour les gérer, bien que je pense qu'il y a déjà quelque chose comme ça pour les applications web.
Vous pouvez utiliser des paramètres optionnels en C # 4.0 sans aucun souci. Si nous avons une méthode comme:
int MyMetod(int param1, int param2, int param3=10, int param4=20){....}
Lorsque vous appelez la méthode, vous pouvez ignorer les paramètres comme ceci:
int variab = MyMethod(param3:50; param1:10);
C# 4.0 implémente une fonctionnalité appelé "paramètres", vous pouvez passer des paramètres par leurs noms, et bien sûr, vous pouvez passer des paramètres, dans l'ordre que vous voulez :)
Bonjour Monde Optionnel
Si vous voulez que le runtime fournisse une valeur de paramètre par défaut, vous devez utiliser reflection pour effectuer l'appel. Pas aussi agréable que les autres suggestions pour cette question, mais compatible avec 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 });
}
}
}
Un élégant et facile qui vous permet d'omettre les paramètres dans n'importe quelle position, en profitant de types nullables est comme suit:
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("-");
}
Les chaînes sont déjà des types nullables donc elles n'ont pas besoin du ?.
Une Fois que vous avez cette méthode, les appels suivants sont valides:
PrintValues (1, 2, 2.2f);
PrintValues (1, c: 1.2f);
PrintValues(b:100);
PrintValues (c: 1.2f, s: "hello");
PrintValues();
Lorsque vous définissez une méthode de cette façon, vous avez la liberté de définir uniquement les paramètres que vous voulez en les nommant . Voir le lien suivant pour plus d'informations sur paramètres nommés et facultatifs:
Arguments nommés et optionnels (Guide de programmation C#) @ MSDN
Je suis d'accord avec stephenbayer. Mais comme il s'agit d'un service web, il est plus facile pour l'utilisateur final d'utiliser une seule forme de webmethod que d'utiliser plusieurs versions de la même méthode. Je pense que dans cette situation les Types Nullables sont parfaits pour les paramètres facultatifs.
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
}
}
Les paramètres optionnels sont pour les méthodes. si vous avez besoin d'arguments optionnels pour une classe et que vous êtes:
-
Utilisation de c # 4.0: utilisez des arguments optionnels dans le constructeur de la classe, une solution que je préfère, car elle est plus proche de ce qui est fait avec les méthodes, donc plus facile à retenir. voici un exemple:
class myClass { public myClass(int myInt = 1, string myString = "wow, this is cool: i can have a default string") { // do something here if needed } }
-
Utilisation des versions c # antérieures à C # 4.0: vous devez utiliser le chaînage constructeur (en utilisant le mot-clé :this), où des constructeurs plus simples mènent à un " maître constructeur". exemple:
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 } }
La façon typique de gérer cela en C# comme stephen l'a mentionné est de surcharger la méthode. En créant plusieurs versions de la méthode avec différents paramètres, vous créez efficacement des paramètres facultatifs. Dans les formulaires avec moins de paramètres, vous appelez généralement le formulaire de la méthode avec tous les paramètres définissant vos valeurs par défaut dans l'appel à cette méthode.
Vous pouvez surcharger votre méthode. Une méthode contient un paramètre GetFooBar(int a)
et l'autre contient les deux paramètres, GetFooBar(int a, int b)
Au lieu des paramètres par défaut, pourquoi ne pas simplement construire une classe de dictionnaire à partir de la chaîne de requête transmise .. une implémentation presque identique à la manière asp.net les formulaires fonctionnent avec querystrings.
C'est-à-dire demande.QueryString["un"]
Cela découplera la classe leaf du code usine / standard.
Vous pouvez également consulter services Web avec ASP.NET . Les services Web sont une api Web générée automatiquement via des attributs sur C# classe.
Un peu en retard à la fête, mais je cherchais la réponse à cette question et finalement trouvé une autre façon de le faire. Déclarez les types de données pour les arguments optionnels de votre méthode web comme étant de type XmlNode. Si l'arg optionnel est omis, cela sera défini sur null, et s'il est présent, vous pouvez obtenir une valeur de chaîne en appelant arg.Valeur, c'est-à-dire
[WebMethod]
public string Foo(string arg1, XmlNode optarg2)
{
string arg2 = "";
if (optarg2 != null)
{
arg2 = optarg2.Value;
}
... etc
}
Ce qui est aussi décent à propos de cette approche, c'est que la page d'accueil générée par. Net pour le ws affiche toujours la liste des arguments (bien que vous perdez les boîtes de saisie de texte pratiques pour les tests).
J'ai un service web à écrire qui prend 7 Paramètres. Chacun est un attribut de requête facultatif à une instruction sql encapsulée par ce service web. Donc, deux solutions de contournement aux paramètres NON facultatifs viennent à l'esprit... les deux assez pauvres:
Method1(param1, param2, paramètre 3, paramètre 4, param 5, param 6, param7) method1(param1, param2, param3, paramètre 4, param5, param 6) méthode 1 (param1, param2, param3, param4, param5, param7)... commencer à voir la photo. De cette façon se trouve la folie. Beaucoup trop d' combinaison.
Maintenant, pour un moyen plus simple qui semble maladroit mais devrait fonctionner: method1 (param1, bool useParam1, param2, bool useParam2, etc...)
C'est un appel de méthode, les valeurs pour tous les paramètres sont requises, et il traitera chaque cas à l'intérieur. Il est aussi clair comment l'utiliser à partir de l'interface.
C'est un hack, mais ça va marcher.
Je devais le faire dans un VB.Net service Web 2.0. J'ai fini par spécifier les paramètres en tant que chaînes, puis les convertir en tout ce dont j'avais besoin. Un paramètre facultatif a été spécifié avec une chaîne vide. Pas la solution la plus propre, mais cela a fonctionné. Faites juste attention que vous attrapez toutes les exceptions qui peuvent se produire.
Pour juste au cas où si quelqu'un veut passer un rappel (ou delegate
) en tant que paramètre optionnel, peut le faire de cette façon.
Paramètre de rappel facultatif:
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;
}
Les paramètres optionnels ne sont que des paramètres par défaut! je vous suggère de donner les deux paramètres par défaut. GetFooBar(int a=0, int b=0) si vous n'avez pas de méthode surchargée, se traduira par un=0, b=0 si vous ne passez pas toutes les valeurs,si vous passez 1, entraînera, passée la valeur de a, 0 et si vous passez 2 valeurs 1er sera attribué à l'un et à b.
J'espère que cela répond à votre question.
Vous pouvez essayer cela aussi
Type 1public void YourMethod(int a=0, int b = 0)
{
//some code
}
Type 2 public void YourMethod(int? a, int? b)
{
//some code
}