对列表运行 Linq 查询时会引发此错误。
我使用 Unity3D 3.0 和 C#(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() 行的原因是什么?
This error is being thrown when running a Linq query over a List.
I am using Unity3D 3.0 with C# (Unity3D uses Mono 2.6). Unity3D, as far as I know, is single-threaded. It works by attaching "scripts" (c# .cs files) that inherit a baseclass, to a "GameObject". Also, Unity controls instantiation and serialization of scripts so you can't use constructors.
I have a RoadNetwork script that holds a reference to RoadNodes and RoadCurves, both of which locate RoadNetwork via a singleton and register/deregister themselves. I've put "mini-factories" in RoadNode and RoadCurve that do the hard work of hooking themselves up to a gameobject.
RoadNode first checks with RoadNetwork to make sure there isnt already a node at that same position, by doing this:
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;
}
Where the appropriate method in RoadNetwork is:
public RoadNode2 GetNodeAtPosition(Vector3 position)
{
var tempList = new List<RoadNode2>();
return tempList.Single(x => x.Position == position);
}
tempList was an attempt at narrowing down the problem but I get precisely the same error. It should be "Nodes.Single(...", but I doubt it matters. I get the same error if I call the Linq query directly in the New() method.
So yes, this Exception throws and points me to that tempList.Single() line. What would the reason be?
发布评论
评论(3)
如果
someEnumerable
中不存在一个元素,someEnumerable.Single(...)
会引发异常。鉴于您刚刚将tempList
声明为空列表,它总是会抛出异常。如果您想在没有元素的情况下检索
null
,请使用SingleOrDefault
。 (如果枚举包含多个一个元素,这仍然会抛出异常。)如果您想要第一个元素,以便您的枚举允许包含任意数量的元素,使用First
(如果可枚举不包含元素,则抛出异常)或FirstOrDefault
(在这种情况下返回null
)。最后,如果您只想检查列表中是否有任何元素与给定谓词匹配,请使用
Any
。someEnumerable.Single(...)
throws an exception if there is not exactly one element insomeEnumerable
. Given that you just declaredtempList
to be an empty list, it will always throw an exception.If you want to retrieve
null
if there are no elements, useSingleOrDefault
. (This will still throw an exception if the enumerable contains more than one element.) If you want the first element, so that your enumerable is allowed to contain any number of elements, useFirst
(throws an exception if the enumerable contains no elements) orFirstOrDefault
(returnsnull
in the case).Finally, if you want to simply check if there are any elements of a list matching a given predicate, use
Any
.我认为 Domenic 的意思是,只要有多个元素与您的谓词匹配,.Single() 就会抛出错误。您的集合 someEnumerable 必须包含您尝试检索的任何单例(而不是编程模式)的重复副本。
I think what Domenic meant to say was that .Single() throws an error whenever more than one element matches your predicate. Your collection someEnumerable must contain duplicate copies of whatever singleton (not the programming pattern) you're trying to retrieve.
听起来您在 Unity 中实现单例模式的方式有问题。如果您在检查列表时收到空引用异常,这意味着该列表尚未初始化,那么您可能没有实例化单例,或者没有访问您实例化的单例。
我通常使用附加到 GameObject 的单例 MonoBehaviour,在第一次访问时实例化和初始化,如下所示:
http://answers.unity3d.com/questions/156746/singleton-and-monobehaviour-in-editor.html
It sounds like there's a problem with the way you're implementing the singleton pattern in Unity. If you're getting a null reference exception when checking a list that mean the list hasn't been initialized, so you're probably either not instantiating the singleton or your not accessing the singleton you instantiated.
I usually use a singleton MonoBehaviour attached to a GameObject that instantiates and initializes on first access like this:
http://answers.unity3d.com/questions/156746/singleton-and-monobehaviour-in-editor.html