在C#中,是否可以使用“尽可能多的参数”调用方法(具有默认参数)?

时间:2012-06-21 23:30:38

标签: c# .net c#-4.0

也就是说,我有一个方法如下:

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

我想通过读取标准的命令行参数数组从命令行调用此方法。显而易见的方法如下:

 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]);

是否有可能以更简洁的方式做到这一点?

5 个答案:

答案 0 :(得分:5)

这是一个替代方案,缺点是必须重新声明默认值常量:

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

您可以通过将字符串声明为const来减少此问题,例如:

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,
        ...);
}

但是,编译器并不能保证,MarketDefault实际上仍然(代码可以在将来重构)Market的默认值。

编辑:这是一个替代解决方案,使用反射:

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

这可能有点难以阅读,并且不会太快,但它会按照您的要求进行,而不需要重复代码,或者对参数的默认值有任何不确定性。您可能希望为太少或太多的参数添加一些错误处理。我更喜欢这个解决方案。

答案 1 :(得分:2)

如何在CreateTaskGroup中使用params这样的

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

答案 2 :(得分:2)

这就是我实现类以保持清洁并将责任分配给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;
    }
}

用法:

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

答案 3 :(得分:0)

这可能是我提出的最好的选择:

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

这是做同样的事情,但不那么简洁:

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

你可以简洁地称之为:

CreateTaskGroup(args);

答案 4 :(得分:0)

我这样做..

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关键字不是强制性的,但可能很方便......