Come puoi usare i parametri opzionali in C #?

Nota: questa domanda è stata posta in un momento in cui C # non supportava ancora i parametri opzionali (cioè prima di C # 4).

Stiamo creando un’API Web generata a livello di codice da una class C #. La class ha il metodo GetFooBar(int a, int b) e l’API ha un metodo GetFooBar che GetFooBar parametri di query come &a=foo &b=bar .

Le classi devono supportare parametri facoltativi, che non sono supportati in C # nella lingua. Qual è l’approccio migliore?

Sorpreso nessuno ha menzionato i parametri opzionali C # 4.0 che funzionano in questo modo:

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

Edit: So che al momento della domanda, C # 4.0 non esisteva. Ma questa domanda è ancora al primo posto in Google per “argomenti opzionali C #” così ho pensato – questa risposta vale la pena essere qui. Scusate.

Un’altra opzione è usare la parola chiave params

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

Chiamato come …

 DoSomething(this, that, theOther); 

In C #, normalmente utilizzerei più forms del metodo:

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

AGGIORNAMENTO: Questo accennato sopra era il modo in cui ho fatto i valori di default con C # 2.0. I progetti su cui sto lavorando ora utilizzano C # 4.0 che ora supporta direttamente i parametri opzionali. Ecco un esempio che ho appena usato nel mio codice:

 public EDIDocument ApplyEDIEnvelop(EDIVanInfo sender, EDIVanInfo receiver, EDIDocumentInfo info, EDIDocumentType type = new EDIDocumentType(EDIDocTypes.X12_814), bool Production = false) { // My code is here } 

Da questo sito:

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

C # consente l’uso dell’attributo [Optional] (da VB, sebbene non funzionale in C #). Quindi puoi avere un metodo come questo:

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

Nel nostro wrapper API, rileviamo i parametri opzionali (ParameterInfo p.IsOptional) e impostiamo un valore predefinito. L’objective è di contrassegnare i parametri come facoltativi senza ricorrere a kludges come avere “facoltativo” nel nome del parametro.

Potresti usare il metodo di overloading …

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

Dipende dalle firme dei metodi, l’esempio che ho dato manca il metodo “int b”, perché avrebbe la stessa firma del metodo “int a”.

Potresti usare i tipi Nullable …

 GetFooBar (int? A, int? B)

È quindi ansible controllare, utilizzando un valore.HasValue, per verificare se è stato impostato un parametro.

Un’altra opzione sarebbe quella di utilizzare un parametro “params”.

 GetFooBar (object params [] args)

Se si volesse utilizzare parametri con nome, sarebbe necessario creare un tipo per gestirli, anche se penso che ci sia già qualcosa di simile per le app Web.

È ansible utilizzare i parametri opzionali in C # 4.0 senza preoccupazioni. Se abbiamo un metodo come:

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

quando chiami il metodo, puoi saltare i parametri in questo modo:

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

C # 4.0 implementa una funzione chiamata “named parameters”, puoi effettivamente passare i parametri con il loro nome e, naturalmente, puoi passare i parametri nell’ordine che vuoi 🙂

Ciao mondo opzionale

Se si desidera che il runtime fornisca un valore di parametro predefinito, è necessario utilizzare il reflection per effettuare la chiamata. Non bello come gli altri suggerimenti per questa domanda, ma compatibile 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 }); } } } 

Un modo semplice ed elegante che ti consente di omettere qualsiasi parametro in qualsiasi posizione, sfruttando i tipi nullable è il seguente:

 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("-"); } 

Le stringhe sono già tipi nullable quindi non hanno bisogno del ? .

Una volta che hai questo metodo, le seguenti chiamate sono tutte valide:

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

Quando definisci un metodo in questo modo hai la libertà di impostare solo i parametri che desideri nominandoli . Vedere il seguente link per ulteriori informazioni sui parametri nominati e facoltativi:

Argomenti nominativi e opzionali (Guida alla programmazione C #) @ MSDN

Sono d’accordo con stephenbayer. Ma poiché è un servizio web, è più facile per l’utente finale utilizzare solo una forma del metodo web, che utilizzare più versioni dello stesso metodo. Penso che in questa situazione i tipi Nullable siano perfetti per i parametri opzionali.

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

i parametri facoltativi sono per i metodi. se hai bisogno di argomenti opzionali per una class e sei:

  • usando c # 4.0: usa gli argomenti opzionali nel costruttore della class, una soluzione che preferisco, poiché è più vicina a ciò che viene fatto con i metodi, così facile da ricordare. ecco un esempio:

     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 le versioni di c # precedenti a c # 4.0: dovresti usare il concatenamento del costruttore (usando: questa parola chiave), dove costruttori più semplici conducono a un “costruttore principale”. esempio:

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

Il modo tipico in cui questo viene gestito in C # come stephen menzionato è quello di sovraccaricare il metodo. Creando più versioni del metodo con parametri diversi, crei in modo efficace parametri facoltativi. Nei moduli con un numero inferiore di parametri, in genere si chiama la forma del metodo con tutti i parametri che impostano i valori predefiniti nella chiamata a tale metodo.

Puoi sovraccaricare il tuo metodo. Un metodo contiene un parametro GetFooBar(int a) e l’altro contiene entrambi i parametri, GetFooBar(int a, int b)

Invece dei parametri predefiniti, perché non costruisci solo una class del dizionario dalla querystring passata … un’implementazione che è quasi identica al modo in cui i moduli di asp.net funzionano con querystring.

cioè Request.QueryString [“a”]

Questo disaccoppierà la class foglia dal codice factory / boilerplate.


Potresti anche voler controllare i servizi Web con ASP.NET . I servizi Web sono una API Web generata automaticamente tramite attributi nelle classi C #.

Un po ‘tardi per la festa, ma stavo cercando la risposta a questa domanda e alla fine ho trovato un altro modo per farlo. Dichiara i tipi di dati per gli argomenti facoltativi del tuo metodo web come tipo XmlNode. Se l’argomento opzionale è omesso, questo verrà impostato su null e, se è presente, è ansible ottenere il valore stringa chiamando arg.Value, ad esempio,

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

Ciò che è anche decente su questo approccio è la home page generata da .NET per la ws continua a mostrare l’elenco degli argomenti (anche se si perdono le pratiche caselle di immissione del testo per i test).

Ho un servizio web per scrivere che richiede 7 parametri. Ciascuno è un attributo di query facoltativo a un’istruzione sql racchiusa da questo servizio Web. Quindi vengono in mente due soluzioni alternative per params non opzionali … entrambi piuttosto poveri:

metodo1 (param1, param2, param 3, param 4, param 5, param 6, param7) metodo1 (param1, param2, param3, param 4, param5, param 6) metodo 1 (param1, param2, param3, param4, param5, param7 ) … inizia a vedere l’immagine. In questo modo giace la follia. Troppe combinazioni.

Ora per un modo più semplice che sembra imbarazzante, ma dovrebbe funzionare: method1 (param1, bool useParam1, param2, bool useParam2, etc …)

Questa è una chiamata al metodo, i valori per tutti i parametri sono obbligatori e gestirà ogni caso al suo interno. È anche chiaro come usarlo dall’interfaccia.

È un hack, ma funzionerà.

Dovevo farlo in un servizio Web VB.Net 2.0. Ho finito per specificare i parametri come stringhe, quindi convertirli in qualunque cosa avessi bisogno. Un parametro facoltativo è stato specificato con una stringa vuota. Non è la soluzione più pulita, ma ha funzionato. Basta fare attenzione a prendere tutte le eccezioni che possono verificarsi.

Per caso, se qualcuno vuole passare un callback (o delegate ) come parametro opzionale, può farlo in questo modo.

Parametro Callback facoltativo:

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

i parametri opzionali non sono altro che i parametri di default! ti suggerisco di fornire entrambi i parametri predefiniti. GetFooBar (int a = 0, int b = 0) se non si dispone di alcun metodo sovraccarico, genererà a = 0, b = 0 se non si passa alcun valore, se si passa 1 valore, si verificherà , valore passato per a, 0 e se si superano 2 valori, 1 sarà assegnato a e secondo a b.

spero che risponda alla tua domanda.

Puoi provare anche questo
Tipo 1
public void YourMethod(int a=0, int b = 0) { //some code }

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