簡體   English   中英

在C#中,是否可以使用“盡可能多的參數”調用方法(具有默認參數)?

[英]In C#, is it possible to call a method (which has default parameters) with “as many parameters as I have”?

也就是說,我有一個如下方法:

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

是否有可能以更簡潔的方式做到這一點?

這是一個替代方案,您必須重新聲明默認值常量:

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

這可能有點難以閱讀,並且不會太快,但它會按照您的要求進行操作,而無需使用重復代碼,或者對參數的默認值有任何不確定性。 您可能希望為太少或太多的參數添加一些錯誤處理。 我更喜歡這個解決方案

如何在CreateTaskGroup中使用params這樣的東西

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

這就是我實現類以保持清潔並將責任分配給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();

這可能是我提出的最好的結果:

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

我這樣做..

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關鍵字不是強制性的,但可以方便...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM