Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有Eof/Eol/EndOfInput属性的C/.NET迭代器_C#_.net_Collections - Fatal编程技术网

C# 具有Eof/Eol/EndOfInput属性的C/.NET迭代器

C# 具有Eof/Eol/EndOfInput属性的C/.NET迭代器,c#,.net,collections,C#,.net,Collections,我需要用复杂的参数解析命令行。每个参数可以包含0个或多个子参数。我从这个开始: static void Main(string[] args) { var argIterator = ((IEnumerable<string>)args).GetEnumerator(); ParseArguments(argIterator); } 在任何时候,我都可以调用iterator.EndOfInput并精确地知道是否访问了所有参数。

我需要用复杂的参数解析命令行。每个参数可以包含0个或多个子参数。我从这个开始:

    static void Main(string[] args)
    {
        var argIterator = ((IEnumerable<string>)args).GetEnumerator();
        ParseArguments(argIterator);
    }
在任何时候,我都可以调用iterator.EndOfInput并精确地知道是否访问了所有参数。但是,这会污染IEnumerator,并且不适用于任何只在末尾需要null的集合

这似乎是一个共同的需要。有更好的解决方案吗?

您没有按照IEnumerator的设计使用它

IEnumerator指定,当调用MoveNext时,值为true意味着我有一个值,而值为Current和false意味着我没有更多的值

如果您想要一个方法,允许您在MoveNext返回false时调用Current,那么您需要编写其他内容,因为这与IEnumerator的契约不匹配


例如,您可以跳过调用其他处理程序或向它们传递空对象。

在您的情况下,最好使用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)
{
    ...
}

上述方法仍然比使用枚举器要好。

将args用作数组并将其传递到ParseArguments中有什么错。然后,您可以在其中使用for循环,并利用数组上的Length属性来确定是否正在解析最后一个参数?这需要沿所有解析器方法传递ref int索引。获取当前元素将始终是args[index]两个值,而不是单个值迭代器.current。Eol的测试将是index>=args.length,再次使用两个值。我更喜欢使用一个表示迭代器的对象。那么为什么不将循环移出ParseArguments呢?然后使用parsearguments[i];在循环内部。您是否可以发布更多的代码,如ParseArguments和它调用的函数之一,以便我们更好地了解您正在尝试执行的操作。示例参数字符串也会很有帮助,尤其是带有子参数的字符串ParseArguments方法只是冰山一角。参数可以有子参数,由其他解析方法ParseOptionFooiterator、ParseOptionK9iterator等解析。到处传递参数和索引似乎不太好。谢谢,但我的问题是,参数可以有不同数量的子参数,你的答案没有考虑到这一点。根据你的要求更新谢谢努力。我知道我可以做这样的事情。这正是我不想做的。我希望迭代器使代码易于阅读,但您不能满足可读性要求。此外,您考虑的是单个级别的子参数,可能不止这些。使用int索引的唯一方法是将ref int index传递给我的所有子解析器,正如我在前面的评论中所说的那样。我觉得这比拥有迭代器更糟糕。我谦虚地不同意。上面的方法将解析逻辑分成两部分,一部分用于提取参数,另一部分用于解析实际内容。这使它更具可读性。使用枚举器肯定会使它更难理解。我已经为另一个可能更符合您要求的场景再次更新了我的答案。我不想调用Current。我只想知道迭代器是否超过了最后一项。我确信它有这些信息,因为它保存索引和参数,所以它可以根据args.length检查索引。@fernacolo:这是一个实现细节。接口只提供Current和MoveNext,因此这些是您唯一可以询问的内容。
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)
{
    ...
}
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)
{
    ...
}