2010-10-13 17 views
5

Este error se produce al ejecutar una consulta Linq sobre una lista.La operación no es válida debido al estado actual del objeto: Linq en la lista

Estoy usando Unity3D 3.0 con C# (Unity3D usa Mono 2.6). Unity3D, hasta donde yo sé, es de un solo hilo. Funciona al adjuntar "scripts" (archivos c .cs) que heredan una clase base a un "GameObject". Además, Unity controla la instanciación y serialización de scripts para que no pueda usar constructores.

Tengo un script de RoadNetwork que contiene una referencia a RoadNodes y RoadCurves, que ubican RoadNetwork a través de un singleton y se registran/anulan el registro. He puesto "mini-fábricas" en RoadNode y RoadCurve que hacen el trabajo duro de conectarse a un objeto de juego.

RoadNode comprueba primero con RoadNetwork para asegurarse de que tampoco hay ya un nodo en la misma posición, al hacer esto:

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; 
} 

Cuando el método apropiado en RoadNetwork es:

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

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

tempList era un intento de reducir el problema, pero obtengo precisamente el mismo error. Debería ser "Nodes.Single (...", pero dudo que importe. Recibo el mismo error si llamo a la consulta Linq directamente en el método New()

Así que sí, esta excepción arroja puntos yo a esa línea tempList.Single(). ¿Qué iba a ser la razón?

Respuesta

13

someEnumerable.Single(...) una excepción si no hay exactamente un elemento en someEnumerable. Teniendo en cuenta que acaba de declarar tempList ser una lista vacía, siempre va a lanzar una excepción.

Si desea recuperar null si no hay elementos, use SingleOrDefault. (Esto todavía arrojará una excepción si el enumerable contiene más de un elemento.) Si desea que el primera elemento, de manera que se permite su enumerables para contener cualquier número de elementos, utilice First (una excepción si el enumerables no contiene elementos) o FirstOrDefault (devuelve null en el caso).

Finalmente, si quiere simplemente verificar si hay algún elemento de una lista que coincida con un predicado determinado, use Any.

+0

Gracias, yo no sabía algo de eso, pero este no es el error (obtendría una referencia nula).Es que la colección por cualquier razón no es válida debido a su estado. –

+3

Es bastante difícil ayudarle si no publica el error exacto. Además, de acuerdo con http://msdn.microsoft.com/en-us/library/bb155325.aspx, el resultado de usar 'Single' en un enumerable con no exactamente un elemento es' InvalidOperationException', no es ningún tipo de referencia nula excepción. – Domenic

+0

Solo quiero decir que las versiones "OrDefault" funcionaron para mi situación particular. También estoy usando Unity y recibía la misma excepción InvalidOperation. En mi caso, estaba usando 'collection.First()' en LINQ. Cambiarlo a '.FirstOrDefault' lo solucionó. Las versiones "OrDefault" de los métodos LINQ siempre son una apuesta segura, parece. – Aaron

0

Creo que lo que Domenic quiso decir es que .Single() arroja un error cada vez que más de un elemento coincide con su predicado. Su colección someEnumerable debe contener copias duplicadas del singleton (no del patrón de programación) que está tratando de recuperar.

0

Parece que hay un problema con la forma en que está implementando el patrón singleton en Unity. Si obtiene una excepción de referencia nula cuando revisa una lista que significa que la lista no se ha inicializado, entonces probablemente no esté instanciando el singleton o no esté accediendo al singleton que creó la instancia.

por lo general uso un MonoBehaviour Singleton unido a una GameObject que instancia e inicializa en el primer acceso como esto:

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

Cuestiones relacionadas