2012-06-21 12 views
5

Cioè, ho un metodo come la seguente:In C#, è possibile chiamare un metodo (che ha parametri predefiniti) con "tanti parametri quanti ne ho"?

public static int CreateTaskGroup(string TaskGroupName, 
    string Market = "en-us", string Project = "MyProject", 
    string Team = "DefaultTeam", string SatelliteID="abc"); 

desidero richiamarlo da riga di comando, leggendo la matrice standard di questi parametri. Il modo più ovvio per farlo sarebbe il seguente:

if (args.Length == 1) CreateTaskGroup(args[0]); 
if (args.Length == 2) CreateTaskGroup(args[0], args[1]); 
if (args.Length == 3) CreateTaskGroup(args[0], args[1], args[2]); 

E 'possibile farlo in modo più conciso?

+1

See questa domanda simile: http://stackoverflow.com/questions/1996426/pass-multiple-optional-parameters-to-ac-sharp-function – Wug

+0

i parametri sono sempre nello stesso ordine? – blitzen

+0

@Wug, non credo che la domanda sia abbastanza simile da essere utile all'OP.(a meno che l'OP non voglia rendere il suo metodo molto meno leggibile) –

risposta

5

Ecco un'alternativa, con il rovescio della medaglia che si deve ridichiarare le costanti valore di default:

CreateTaskGroup(
    args[0], 
    args.ElementAtOrDefault(1) ?? "en-us", 
    args.ElementAtOrDefault(2) ?? "MyProject", 
    args.ElementAtOrDefault(3) ?? "DefaultTeam", 
    args.ElementAtOrDefault(4) ?? "abc"); 

È possibile ridurre questo problema dichiarando le stringhe come const s, ad esempio:

public const string MarketDefault = "en-us"; 
public static int CreateTaskGroup(string TaskGroupName, 
    string Market = MarketDefault, ...) 

static void Main(string[] args) 
{ 
    CreateTaskGroup(
     args[0], 
     args.ElementAtOrDefault(1) ?? MarketDefault, 
     ...); 
} 

Ma poi non è garantito dal compilatore, né apertamente ovvio, che MarketDefault sia, in effetti, ancora (il codice può essere refactored in futuro) il default per Market.

Edit: Ecco una soluzione alternativa, utilizzando la riflessione:

var argsForMethod = new List<string>(args); 
var m = typeof(Program).GetMethod("CreateTaskGroup"); 
foreach (var p in m.GetParameters().Skip(args.Length)) 
    if (p.Attributes.HasFlag(ParameterAttributes.HasDefault)) 
     argsForMethod.Add((string)p.DefaultValue); 
    else 
     throw new NotImplementedException(); 
var result = (int)m.Invoke(null, argsForMethod.ToArray()); 

Questo può essere un po 'difficile da leggere, e non sarà troppo veloce, ma fa quello che hai chiesto, senza ricorrere a codice ripetitivo , o con incertezza sul valore predefinito dei parametri. Probabilmente vorrai aggiungere qualche gestione degli errori per troppi pochi o troppi parametri. Preferisco questa soluzione.

2

Come sull'utilizzo params in CreateTaskGroup qualcosa di simile

public static int CreateTaskGroup(params string[] args) 
{ 
    for (int i = 0 ; i < args.Length ; i++) 
    { 
     ............ 
0

Questo è probabilmente meglio di quello che mi è venuta in mente:

public static int CreateTaskGroup(string[] arguments) 
{ 
    // optional error handling here 

    string TaskGroupName = arguments[0]; 
    string Market  = arguments.ElementAtOrDefault(1) ?? "en-us"; 
    string Project  = arguments.ElementAtOrDefault(2) ?? "MyProject"; 
    string Team   = arguments.ElementAtOrDefault(3) ?? "DefaultTeam"; 
    string SatelliteID = arguments.ElementAtOrDefault(4) ?? "abc"; 

    // function body as it was 

Questo fa la stessa cosa, ma è meno concisa :

public static int CreateTaskGroup(string[] arguments) 
{ 
    string TaskGroupName, Market, Project, Team, SatelliteID; 
    switch (arguments.Length) 
    { 
    case 5: 
     string SatelliteID = arguments[4] ?? "abc"; 
     goto case 4; 
    case 4: 
     string Team   = arguments[3] ?? "DefaultTeam"; 
     goto case 3; 
    case 3: 
     string Project  = arguments[2] ?? "MyProject"; 
     goto case 2; 
    case 2: 
     string Market  = arguments[1] ?? "en-us"; 
     goto case 1; 
    case 1: 
     string TaskGroupName = arguments[0]; 
     break; 
    case 0: 
     // error handling here; 
    } 

    // function body as it was 

si potrebbe chiamare sinteticamente così:

CreateTaskGroup(args); 
+1

'argomenti [4]' non sta per essere nullo, sta andando a gettare un fuori limite eccezione – climbage

+0

mi sono reso conto che dopo che ho postato. l'istruzione switch lo ha risolto, ma lo ha reso brutto allo stesso tempo. :( – Wug

+0

Ma ora tutte le variabili hanno un ambito per l'istruzione switch unico. Non è possibile usarli nel resto della funzione. – user1096188

2

Ecco come implementare la classe per mantenere le cose pulite e assegnare la responsabilità di conoscere i valori predefiniti al TaskGroupCreator.

public class TaskGroupCreator 
{ 
    private string[] values; 

    public TaskGroupCreator(string[] values) 
    { 
     this.values = values; 
    } 

    public string TaskGroupName 
    { 
     get { return values[0]; } 
    } 

    public string Market 
    { 
     get { return this.GetElement(1, "en-us"); } 
    } 

    public string Project 
    { 
     get { return this.GetElement(2, "MyProject"); } 
    } 

    public string Team 
    { 
     get { return this.GetElement(3, "DefaultTeam"); } 
    } 

    public string SatelliteID 
    { 
     get { return this.GetElement(4, "abc"); } 
    } 

    public int CreateTaskGroup() 
    { 
     // Do stuff with your properties... 
    } 

    private string GetElement(int index, string defaultValue) 
    { 
     return this.values.ElementAtOrDefault(index) ?? defaultValue; 
    } 
} 

Usage:

var taskGroup = new TaskGroupCreator(args).CreateTaskGroup(); 
+0

che è così Java ... – user1096188

+0

Ah! Questo è interessante. Ho mai programmato in Java ... Il pattern deve essere quindi trasferito alla comunità .NET. –

0

lo farei in questo modo ..

CreateTaskGroup(args); 

//..... 

public static int CreateTaskGroup(params string[] args) { 
    if (args.Length == 0) throw new Exception("nope!"); 
    args = args.Concat(Enumerable.Range(0, 5 - args.Length) 
     .Select<int, string>(_ => null)).ToArray(); 
    string TaskGroupName = args[0]; 
    string Market = args[1] ?? "en-us"; 
    string Project = args[2] ?? "MyProject"; 
    string Team = args[3] ?? "DefaultTeam"; 
    string SatelliteID = args[4] ?? "abc"; 
    //...... 
} 

params parola chiave non è obbligatorio, ma potrebbe essere conveniente ...

Problemi correlati