1

我有一个带有 List 的类,我正在另一个类方法中访问它。这很好,但是当我尝试在 do-loop 中使用 List 时,我总是得到一个“ArgumentOutOfRangeExcetpion”。我真的很困惑为什么在 do-loop 中使用 List 会导致它为空,或者至少这是我认为正在发生的事情。如果有人可以向我解释为什么会发生这种情况,那将是非常有启发性的,也许我可以弄清楚我将如何让它发挥作用。

这是我的方法:

private void ListToAttributes()
    {
        int count = -1;

        //Finds Attribute starting Line.
        do
        {
            count = count + 1;

        } while (Player.PlayerList[count] != "Attributes;");

        //Adds all Attributes to a list
        List<string> TypeAndAmount = new List<string>();

        do
        {
            TypeAndAmount.Add(Player.PlayerList[count]);
            count = count + 1;
        } while (Player.PlayerList[count] != ".");

        //Sorts by type and adds amount to Player Class


        foreach (string Line in TypeAndAmount)
        {
            string[] Type = Line.Split(' ');

            if (Type[0] == "Mind") { Player.Mind = int.Parse(Type[1]); }
            if (Type[0] == "Body") { Player.Body = int.Parse(Type[1]); }
            if (Type[0] == "Soul") { Player.Soul = int.Parse(Type[1]); }
        }
    }
4

4 回答 4

3

您的第一个循环将导致ArgumentOutOfRangeException列表中没有项目与字符串匹配。在这种情况下,您将愉快地走过列表的末尾。你的第二个循环有同样的问题。

此外,我认为您必须count在两个循环之间再增加一次 - 目前您正在将项目添加"Attributes;"到列表中TypeAndAmount。这也将导致,ArgumentOutOfRangeException因为在空格处拆分字符串"Attributes;"只会产生一个字符串,并且您正在Type[1]最后一个循环中访问。

我建议使用一些 LINQ 重写您的代码(包括跳过该项目的步骤"Attributes;")。

// Skip everything until we find 'Attributes;'.
var stepOne = Player.PlayerList.SkipWhile(entry => entry != "Attributes;");

// Skip over 'Attributes;'.
var stepTwo = stepOne.Skip(1);

// Take everything until we find '.'.
var stepThree = stepTwo.TakeWhile(entry => entry != ".");

// Stuff everything we selected into a new list.
var typeAndAmount = stepThree.ToList();

您还可以将所有内容放在一个语句中 - 不那么冗长但更难调试。

var typeAndAmount = Player.PlayerList
                          .SkipWhile(entry => entry != "Attributes;")
                          .Skip(1)
                          .TakeWhile(entry => entry != ".")
                          .ToList();
于 2012-12-18T18:49:21.847 回答
1

我正在根据最佳猜测修改我的答案。当您点击第二个循环时,Player.PlayerList[count] 仍将等于“属性”。然后您进入第二个循环并将“属性”添加到 TypeAndAmount。当您尝试在该行上使用 Line.Split(' ') 时,它只会返回一个包含一个项目的数组。Type[1] 将抛出 ArgumentOutOfRangeException。

我认为如果您在第二个循环之前添加 count = count +1,那将解决您的问题。

找到第一个“属性”部分的另一种聪明(我认为)方法是将其全部包装在一行中:

int count = -1;
while (Player.PlayerList[count++] != "Attributes;");

++ 表示法只是一种更快的书写方式 count = count + 1。希望您会发现它很有用。:)

于 2012-12-18T18:45:56.910 回答
1

我看到一些可能导致异常的错误。在您的第一个循环中,您需要检查并确保数组不为空,并且您需要有一个条件来检查数组大小,以防“属性”不存在。也许尝试:

if (Player.PlayerList.Length > 0){
  do
  {
    count = count + 1;
  }while (count < Player.PlayerList.Length && Player.PlayerList[count] != "Attributes;");

请注意,如果未找到 Attributes,您可能应该抛出您自己的异常。对于第二个循环,您需要添加类似的条件:

if (count < Player.PlayerList.Length){
  do
  {
      TypeAndAmount.Add(Player.PlayerList[count]);
      count = count + 1;
  } while (count < Player.PlayerList.Length && Player.PlayerList[count] != ".");
}

请注意,这些只会防止异常。如果您的列表没有按照此方法所期望的方式排列,您仍然会遇到问题。

于 2012-12-18T19:09:01.877 回答
0

问题出在您的 Do 循环中,您将计数增加 1,然后对其进行评估。这会导致您的计数大于元素的数量。

这会起作用:

 while (count < Player.PlayerList.Count && Player.PlayerList[count] != "Attributes;");
于 2012-12-18T18:46:50.650 回答