【问题标题】:Very weird! My list returns ArgumentOutofRangeException when trying to add很奇怪!我的列表在尝试添加时返回 ArgumentOutofRangeException
【发布时间】:2019-03-28 21:31:22
【问题描述】:

我正在为程序执行一系列任务,因此我启动了一个 List 对象。 这个列表是另一个类的列表,它具有取决于类型(整数)做什么(任务)的信息。 这是一个主机与客户端的谈话,他们都有类(有点不同,只是我对类型的理解(客户端任务类型 0!= 主机任务类型 0))并且我的主机列表运行良好,但客户端没有.

我的 NetObjects 列表在尝试添加(NetObject 的)类时返回 ArgumentOutOfRangeException(我将保留代码示例)。 我不知道为什么会这样,因为 List 应该是无限的,并且当您添加时没有索引或其他东西(它说索引必须是非负数并且小于集合的大小)。

这是错误:

ArgumentOutOfRangeException:索引超出范围。必须是非负数且小于集合的大小。 参数名称:索引 System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument 参数,System.ExceptionResource 资源)(在:0) System.ThrowHelper.ThrowArgumentOutOfRangeException () (at :0) System.Collections.Generic.List`1[T].get_Item(System.Int32 索引)(在:0) Networking.Update () (在 Assets/Scripts/Networking.cs:225)

它说了一些我不知道为什么的get item,因为我(在代码中)使用带有索引的任务引用(读取它)并且它什么也没发生,但只有当我想添加到 NetObject 到对象类。 我将显示主机代码,因为它有效,而客户端无效,我不明白为什么。

我试图通过加锁让它变得更好(这样就没有覆盖),但从我的角度来看,除了让它变得更好之外,我没有做更多的事情。

这是制作任务的客户端部分(在 Unity 中),我使用任务是因为如果不是来自主线程(并且我使用线程来接收和发送信息(客户端和主机之间的对话)。

for (int i = 0; i < PendingClient.Count; i++) {
            if (PendingClient[i].id > -1)
                lock (lockingClient) {
                    switch (PendingClient[i].type) {
                        case 0:
                            GameObject go = null;
                            if (GetObjectFromId(PendingClient[i].id, ref go)) {
                                go.transform.position = new Vector3(PendingClient[i].px,
                                PendingClient[i].py, PendingClient[i].pz);

                                go.transform.rotation = Quaternion.Euler(PendingClient[i].rx,
                                PendingClient[i].ry, PendingClient[i].rz);
                            } else {
                                Objects.Add(new NetObject(PendingClient[i].id,
                                PendingClient[i].objectType, PendingClient[i].name,
                                PendingHost[i].prefabName,
                                Instantiate(Resources.Load("Prefabs/" +
                                PendingClient[i].prefabName) as GameObject,
                                new Vector3(PendingClient[i].px, PendingClient[i].py,
                                PendingClient[i].pz), Quaternion.Euler(PendingClient[i].rx,
                                PendingClient[i].ry, PendingClient[i].rz))));
                            }
                            break;
                    }
                    PendingClient.RemoveAt(i);
                }
        }

错误出现在最后一个 else 的正下方。

以及有效的主机代码:

for (int i = 0; i < PendingHost.Count; i++) {
            lock (lockingHost) {
                if (PendingHost[i].id > -1) {
                    switch (PendingHost[i].type) {
                        case 0: // Add Object
                            Objects.Add(new NetObject(PendingHost[i].id, PendingHost[i].objectType, PendingHost[i].name, PendingHost[i].prefabName, Instantiate(Resources.Load("Prefabs/" + PendingHost[i].prefabName) as GameObject, Vector3.zero, Quaternion.identity)));
                            break;
                        case 1: // Change Transform
                            GameObject go = null;
                            GetObjectFromId(PendingHost[i].id, ref go);
                            go.transform.position = new Vector3(PendingHost[i].px, PendingHost[i].py, PendingHost[i].pz);
                            go.transform.rotation = Quaternion.Euler(PendingHost[i].rx, PendingHost[i].ry, PendingHost[i].rz);
                            break;
                    }
                    PendingHost.Remove(PendingHost[i]);
                }
            }
        }

我不是信息工程师,但我尽力编写更好的代码。

感谢您的提前。

【问题讨论】:

  • 我的猜测是,它与从循环中的列表中删除有关,因此当您到达 10 元素列表中的 i = 6 时,您会遇到错误。为什么不在循环后清除列表?只是一个想法。
  • 如果您需要在使用 for 循环遍历列表时从列表中删除一个元素,那么使用旧技巧从末尾开始枚举元素 for (int i = PendingHost.Count -1; i >= 0; i--) {
  • 好的,它可能会起作用!
  • i 不仅超出范围,而且您正在跳过元素,因为删除后,下一个元素将替换 i 处删除的元素,但 for 语句仍然递增i.

标签: c# list add


【解决方案1】:

你打电话

PendingClient.RemoveAt(i);

里面

for (int i = 0; i < PendingClient.Count; i++) {

所以i 最终会超出范围。

除此之外:不要做十几次PendingClient[i],而是做

var current = PendingClient[i] 在前面,然后使用current

【讨论】:

  • 这是正确的,也浪费了对 PendingClient 的调用。还可以像上面提到的@Steve 那样反转你的循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
相关资源
最近更新 更多