由于对象的当前状态,操作无效 - 在列表上使用Linq

5
当在List上运行Linq查询时,会抛出此错误。
我使用的是带有C#的Unity3D 3.0(Unity3D使用Mono 2.6)。据我所知,Unity3D是单线程的。它通过将继承基类的“脚本”(c# .cs文件)附加到“GameObject”上来工作。此外,Unity控制脚本的实例化和序列化,因此您不能使用构造函数。
我有一个RoadNetwork脚本,它保存对RoadNodes和RoadCurves的引用,两者都通过单例定位RoadNetwork并注册/注销自己。我在RoadNode和RoadCurve中放置了“迷你工厂”,这些工厂完成了将自己连接到游戏对象的艰苦工作。
RoadNode首先通过执行以下操作与RoadNetwork进行检查,以确保该位置没有已经存在的节点:
public static RoadNode2 New(float x, float y, float z)
{
    //First try to find an existing one
    var rn = RoadNetwork.Instance.GetNodeAtPosition(new Vector3(x, y, z))
             ?? UnityReferenceHelper.GetNewGameObjectFor<RoadNode2>(
                 "RoadNode_" + (RoadNetwork.Instance.Nodes.Count + 1).ToString("D3"),
                 RoadNetwork.Instance.transform.FindChild("Nodes"));

    rn.Position = new Vector3(x, y, z);

    rn.gameObject.active = true;

    return rn;
}

RoadNetwork 中适当的方法是:

public RoadNode2 GetNodeAtPosition(Vector3 position)
{
    var tempList = new List<RoadNode2>();

    return tempList.Single(x => x.Position == position);
}

tempList是缩小问题范围的尝试,但我收到了完全相同的错误。应该是 "Nodes.Single(...",但我怀疑这并不重要。如果我在New()方法中直接调用Linq查询,我会得到相同的错误。

所以是的,这个异常抛出并指向那个tempList.Single()行。原因是什么呢?

3个回答

15

someEnumerable.Single(...)方法在someEnumerable集合中元素数量不为1时会抛出异常。由于您刚刚声明了tempList为空列表,因此它总是会抛出异常。

如果您想要在没有元素的情况下检索到null,请使用SingleOrDefault。(如果可枚举对象包含多个元素,仍然会抛出异常。)如果您想要第一个元素,以便允许您的枚举对象包含任意数量的元素,请使用First(如果可枚举对象不包含元素,则抛出异常)或FirstOrDefault(在这种情况下返回null)。

最后,如果您只想检查是否有列表中的任何元素与给定的条件相匹配,请使用Any方法。


谢谢,我不知道其中的一些内容,但这不是错误(我会得到一个空引用)。问题在于由于其状态,该集合出于某种原因无效。 - George R
3
如果您没有发布精确的错误信息,那么帮助您会比较困难。此外,根据http://msdn.microsoft.com/en-us/library/bb155325.aspx,在对一个枚举类型使用`Single`方法得到不止一个元素时,结果是 InvalidOperationException 异常,而不是任何一种空引用异常。 - Domenic
我只想说,“OrDefault”版本适用于我的特定情况。我也在使用Unity,遇到了相同的InvalidOperation异常。在我的情况下,我在LINQ中使用了collection.First()。将其更改为.FirstOrDefault即可解决问题。似乎“OrDefault”版本的LINQ方法总是一个安全的选择。 - Aaron

0
我认为Domenic的意思是,当你的谓词匹配到多个元素时,.Single()会抛出错误。你的集合someEnumerable必须包含重复的副本,无论你试图检索什么单例(不是编程模式)。

0
似乎你在 Unity 中实现单例模式的方式有问题。如果在检查列表时出现空引用异常,则意味着该列表尚未初始化,因此你可能没有实例化单例或者无法访问你实例化的单例。
我通常使用一个附加到游戏对象上的 Singleton MonoBehaviour,在首次访问时进行实例化和初始化,像这样:

http://answers.unity3d.com/questions/156746/singleton-and-monobehaviour-in-editor.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接