如何为System.CommandLine同一选项传递多个值?
如何在C#控制台应用中通过命令行传递多个数字参数?
初始问题
我想给C#控制台应用传递多个数字,代码示例如下:
private const long DEFAULT_ALPHA_VALUE = 1234567890L; private static long[] alphas = { DEFAULT_ALPHA_VALUE }; public static async Task Main() { Option<long[]> alphaOption = new ( aliases: new[] { "-a", "--alpha" }, getDefaultValue: () => new[] { DEFAULT_ALPHA_VALUE }, description: "Numerical alpha values" ); RootCommand rootCommand = new("A test app for multiple numerical values option"); rootCommand.AddGlobalOption(alphaOption); rootCommand.SetHandler(a => { alphas = a; }, alphaOption); await RunInvokeAsync(rootCommand, "-a", "1234"); await RunInvokeAsync(rootCommand, "-a", "1234", "5678"); // 错误:Unrecognized command or argument '5678'. await RunInvokeAsync(rootCommand, "-a", "1234 5678"); // 错误:Cannot parse argument '1234 5678' for option '-a' as expected type 'System.Int64'. await RunInvokeAsync(rootCommand, "-a", "1234,5678"); // 错误:Cannot parse argument '1234,5678' for option '-a' as expected type 'System.Int64'. } private static async Task RunInvokeAsync(RootCommand rootCommand, params string[] args) { int status = await rootCommand.InvokeAsync(args); Console.WriteLine($"args: {JsonSerializer.Serialize(args)}, status: {status}, alphas: {JsonSerializer.Serialize(alphas)}"); }
我期望用以下任意一种命令传递多个数字:
dotnet run --project MultipleValuesOption.csproj -- -a 1234 5678 dotnet run --project MultipleValuesOption.csproj -- -a 1234,5678
但运行时均出现错误,请问该如何正确传递多个数字?是代码逻辑有问题,还是调用方式不对?
更新后的问题
按照建议给选项添加了AllowMultipleArgumentsPerToken = true,但新增第二个选项后,参数仍未被正确读取。代码示例:
private const long DEFAULT_ALPHA_VALUE = 13579L; private static long[] alphas = { DEFAULT_ALPHA_VALUE }; private const long DEFAULT_BETA_VALUE = 24680L; private static long[] betas = { DEFAULT_BETA_VALUE }; public static async Task Main(string[] args) { Option<long[]> alphaOption = new ( aliases: new[] { "-a", "--alpha" }, getDefaultValue: () => new[] { DEFAULT_ALPHA_VALUE }, description: "Numerical alpha values" ) { AllowMultipleArgumentsPerToken = true, }; Option<long[]> betaOption = new ( aliases: new[] { "-b", "--beta" }, getDefaultValue: () => new[] { DEFAULT_BETA_VALUE }, description: "Numerical beta values" ) { AllowMultipleArgumentsPerToken = true, }; RootCommand rootCommand = new("A test app for multiple numerical values option"); rootCommand.AddGlobalOption(alphaOption); rootCommand.AddGlobalOption(betaOption); rootCommand.SetHandler(a => { alphas = a; }, alphaOption); rootCommand.SetHandler(b => { betas = b; }, betaOption); await RunInvokeAsync(rootCommand, args); await RunInvokeAsync(rootCommand, "-a", "1234", "5678"); } private static async Task RunInvokeAsync(RootCommand rootCommand, params string[] args) { int status = await rootCommand.InvokeAsync(args); Console.WriteLine($"args: {JsonSerializer.Serialize(args)}, status: {status}, alphas: {JsonSerializer.Serialize(alphas)}, betas: {JsonSerializer.Serialize(betas)}"); }
输出显示alphas始终保持默认值13579,没有读取命令行传入的参数:
args: [], status: 0, alphas: [13579], betas: [24680] args: ["-a","1234","5678"], status: 0, alphas: [13579], betas: [24680]
解决方案
1. 单选项多参数的正确配置
要支持-a 1234 5678这种空格分隔的多参数传递,需要为Option<long[]>配置两个关键属性:
AllowMultipleArgumentsPerToken = true:允许一个选项令牌后跟随多个参数值Arity = ArgumentArity.ZeroOrMore:明确参数可以是0个或多个(数组类型默认已隐含,但显式设置更清晰)
修改后的单个选项代码:
Option<long[]> alphaOption = new( aliases: new[] { "-a", "--alpha" }, getDefaultValue: () => new[] { DEFAULT_ALPHA_VALUE }, description: "Numerical alpha values" ) { AllowMultipleArgumentsPerToken = true, Arity = ArgumentArity.ZeroOrMore };
此时使用dotnet run -- -a 1234 5678即可正确传递多个数字。
2. 多选项时的处理器绑定问题
你遇到的第二个问题是因为多次调用SetHandler会覆盖之前的处理器,RootCommand只能有一个主处理器。正确做法是创建一个包含所有选项参数的处理器,一次性绑定所有选项:
// 替换原来的两次SetHandler调用 rootCommand.SetHandler((a, b) => { alphas = a; betas = b; }, alphaOption, betaOption);
这样就能同时读取-a和-b的参数值。
3. 支持逗号分隔的参数(可选)
如果想同时支持-a 1234,5678这种逗号分隔的格式,需要自定义参数解析器:
Option<long[]> alphaOption = new( aliases: new[] { "-a", "--alpha" }, parseArgument: (context, value) => { // 分割逗号并转换为long数组 return value.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(long.Parse) .ToArray(); }, getDefaultValue: () => new[] { DEFAULT_ALPHA_VALUE }, description: "Numerical alpha values" ) { AllowMultipleArgumentsPerToken = true, Arity = ArgumentArity.ZeroOrMore };
此时两种传递方式-a 1234 5678和-a 1234,5678都能生效。
内容的提问来源于stack exchange,提问作者Alexander Farber
相关产品推荐
相关产品推荐

