【问题标题】:What is this ArgumentOutOfRangeException caused by?这个 ArgumentOutOfRangeException 是由什么引起的?
【发布时间】:2014-12-18 13:21:15
【问题描述】:

我有一个让我发疯的问题。我正在使用一个通用列表,每当我尝试将其第一个(或最后一个?)索引分配给一个变量时,它就会抛出一个 ArgumentOutOfRangeException。这是一大堆代码,因此我将尝试仅提取相关内容。所以这里是:

private string GetRuleByName(string name, List<string> rules)
{
    if(rules != null)
    {
        List<string> todo = new List<string>();
        todo.AddRange(rules);

        while(rules.Count != 0)
        {
            string r = todo[0]; // <- Error 'ArgumentOutOfRangeException' here
            todo.RemoveAt(0);

            // ...
        }
    }
}

这就是我调用方法的方式:

void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
    string currentRule = GetRuleByName(treeView.SelectedNode.FullPath, ruleCollection)
    // the string list "ruleCollection" always contains
    // strings and thus is never empty
}

尽管这不是对正在发生的事情的非常详细的介绍,因为我不得不截取一段复杂的代码,但我真的希望其他人能看到导致错误的原因。

非常感谢您至少看一下!

编辑

这就是方法的样子。我没有改变任何东西,以展示它的真实内容。我希望这对某人有意义:

private Rule GetRuleByNameOrId(string stName, List<Rule> rules)
{
    if(rules != null)
    {
        string searchName = stName.ToLower().Trim();
        string subName = "";
        int slashPos = searchName.IndexOf('/');

        if(slashPos != -1)
        {
            if(slashPos != searchName.Length)
                subName = searchName.Substring(slashPos + 1);
            searchName = searchName.Substring(0, slashPos);
        }

        List<Rule> todo = new List<Rule>();
        todo.AddRange(rules);

        while(todo.Count != 0)
        {
            Rule r = (Rule)todo[0];
            todo.RemoveAt(0);

            if(r.Name.ToLower() == searchName || r.Id.ToLower() == searchName)
            {
                if(subName != "")
                {
                    Rule subRule = GetRuleByNameOrId(subName, r.Children);

                    if(subRule != null)
                        return subRule;
                }
                else
                {
                    return r;
                }
            }
            if(r.Children != null && r.Children.Count != 0)
                todo.AddRange(r.Children);
        }//end while
    }//end if(rules != null)
    return null;
}

【问题讨论】:

  • 您在 rules.Count != 0 时循环,但您使用 todo.RemoveAt(0) 从待办事项中删除项目 - 因此您在待办事项中用完了项目并且索引超出范围,因为 rules.Count 始终 > 0。你的意思是改用while(todo.Count != 0)
  • todo 是一个空列表 - 它没有第 0 个元素
  • todo 不是空 Preston - 在循环之前有一个 todo.AddRange 调用,并且由于 OP 说 rules 永远不会为空,我们必须查看代码以查看todo 的索引可能超出范围
  • 你能解释一下从待办事项列表中删除项目的逻辑吗?琐碎循环错误的一部分可能有更好的方法来准备待办事项列表,知道所需的逻辑。在不知道省略的代码的情况下,您的待办事项列表将在循环结束时完全为空,那么为什么要首先在其中添加元素呢?
  • @Steve 我知道不可能看到发生了什么。正如我在问题中所说,进行有意义的剪辑并不容易,因为代码非常复杂。不过我还是会试一试的。

标签: c# list indexing argumentexception


【解决方案1】:

听起来您想要以下内容:

private string GetRuleByName(string name, List<string> rules)
{
    if(rules != null)
    {
        List<string> todo = new List<string>();
        todo.AddRange(rules);

        while(todo.Count != 0) // <-- Minor mod here
        {
            string r = todo[0]; 
            todo.RemoveAt(0);

            // ...
        }
    }
}

否则,您将无限循环 rules.Count,因为 rules 的大小不会改变

这工作正常,直到 todo 为空,然后您会收到异常,因为元素 0 不再存在,因为您已将它们全部删除!

【讨论】:

  • 谢谢!这摆脱了 ArgumentException。不过还有一个问题。您能否看一下我添加到问题中的原始方法,并告诉我您的修改是否符合原始上下文?因为现在在 if(r.Name.ToLower()...) 行下面的三行抛出 NullReferenceException,我不确定这是否是因为我现在正在检查 todo.Count。
  • 看不到空引用的任何充分理由。唯一可能的情况是:NameRule 实例之一上为空,或者r.Children 集合在其中一个规则(或原始规则列表)中包含空引用。您是否尝试过调试 - 或者有什么原因您没有尝试过调试?
  • 是的,我试过了,终于成功了。 r.Name 确实为空。再次感谢您的帮助!
【解决方案2】:

你确定不想要这个吗:

while(rules.Count != 0)
{
    string r = rules[0]; // <- Error 'ArgumentOutOfRangeException' here
    rules.RemoveAt(0);

?

按照您现在编写的方式,您得到了一个实际上是无限的循环,除了您最终从 todo 列表中删除所有元素,此时您抛出异常(因为在空列表甚至第 0 个元素都不存在)。

【讨论】:

  • 感谢您抽出宝贵时间,但代码需要两个单独的列表才能工作。我知道你不应该知道的。只是说说而已。
  • 只是在说什么?我什至不知道你写的东西是什么意思。这里的底线是你不能绕过从一个列表中删除元素,而是使用不同列表的计数来决定你已经完成了。也许您希望到处都是todo 而不是到处都是rules,但是一种或另一种方式,您必须坚持使用相同的列表,而不是将两者混合。 这是最重要的部分。
  • 点了。我更新了我的问题。我不确定,但现在可能对你来说更有意义,或者更确切地说不是。它是原始方法,还包括在代码中其他地方声明的变量。
猜你喜欢
  • 2012-05-25
  • 1970-01-01
  • 2011-04-02
  • 2013-03-21
  • 2011-12-03
  • 2011-12-24
  • 2011-12-07
  • 1970-01-01
相关资源
最近更新 更多