我需要用复杂的参数解析命令行。每个参数可以包含0个或更多个子参数。我从这开始:
static void Main(string[] args)
{
var argIterator = ((IEnumerable<string>)args).GetEnumerator();
ParseArguments(argIterator);
}
然而事实证明这还不够,因为在任何特定时刻我都需要知道我是否在EndOfInput。虽然MoveNext()返回false,但这可以在解析期间的任何地方发生,并且IEnumerator
不会让我知道发生了这种情况,除了调用Current引发异常。我认为这不值得创建自定义枚举类。
我使用的技巧是将所有字符串添加到具有args.length + 1
元素的新数组中。附加元素是null
。然后我可以有这个扩展方法:
static class EnumeratorExtension
{
private static bool EndOfInput(this IEnumerator<string> iterator)
{
return iterator.Current == null;
}
}
在任何时候,我都可以致电iterator.EndOfInput()
并准确了解是否所有参数都被访问过。但是,这会污染IEnumerator
并且不适用于任何集合(仅在最后需要null
)。
这似乎是一种常见的需求。有更好的解决方案吗?
答案 0 :(得分:0)
您没有使用设计使用的IEnumerator
。
合同IEnumerator
指定当您致电MoveNext()
时,true
的值为“我有一个值且位于Current
”且{{1} }意思是“我没有更多的价值”。
如果您想要一种允许您在false
返回Current
时致电MoveNext()
的方法,则需要编写其他内容(因为这与false
不匹配'合同。
例如,您可以跳过调用其他处理程序或向其传递IEnumerator
对象。
答案 1 :(得分:0)
在您的情况下,最好使用for循环。调查员不是为你正在做的事而设计的。
你可以这样做:
static void Main(string[] args)
{
foreach (string arg in args)
{
ParseArgument(arg); // Parse each argument individually.
}
}
如果您需要子参数,那么您可以将逻辑拆分为多个方法:
static void Main(string[] args)
{
ParseArguments(args);
}
static void ParseArguments(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
switch (args[i])
{
// Single arguments. (No sub-arguments)
case "/a":
case "/b":
case "/c":
ParseArgument(args[i]); // Parse individual argument(s)
break;
// Double-arguments (1 sub-argument)
case "/username":
case "/password":
case "/filepath":
string nextArg = (i + 1 < args.Length ? args[i + 1] : null);
ParseArgument(args[i], nextArg); // Parse individual argument(s)
i++;
break;
// Triple-arguments (2 sub-arguments)
case "/makeAndModel":
case "/nameAndAddress":
string nextArg = (i + 1 < args.Length ? args[i + 1] : null);
string nextArg2 = (i + 2 < args.Length ? args[i + 2] : null);
ParseArgument(args[i], nextArg, nextArg2); // Parse individual argument(s)
i += 2;
break;
// Invalid arguments
default:
ShowHelp();
break;
}
}
// Parse individual argument(s)
static void ParseArgument(params string[] args)
{
...
}
请注意,您还可以通过其他方式实现ParseArgument(params string[] args)
,例如3种不同的重载方法,每种方法都有不同数量的参数;或者你可以为每个参数实现一个方法(例如ParseUserName
,ParsePassword
等。)
编辑:如果您需要不同数量的子参数,并且您不知道其中有多少个子参数(例如,子参数的数量取决于其实际内容参数),然后您可以执行以下操作:
static void Main(string[] args)
{
int parsedCount = 0;
for (int index = 0; index < args.Length; index += parsedCount)
{
parsedCount = ParseArguments(args);
}
}
static int ParseArguments (string[] args, int index)
{
...
}
上述情况仍然优于使用枚举器。