2010-10-13 12 views
5

Dieser Fehler wird ausgelöst, wenn eine Linq-Abfrage über eine Liste ausgeführt wird.Die Operation ist aufgrund des aktuellen Status des Objekts nicht gültig - Linq in der Liste

Ich verwende Unity3D 3.0 mit C# (Unity3D verwendet Mono 2.6). Unity3D ist, soweit ich weiß, single-threaded. Es funktioniert, indem man "scripts" (C# .cs-Dateien), die eine Basisklasse erben, an ein "GameObject" anfügt. Außerdem steuert Unity die Instantiierung und Serialisierung von Skripts, sodass Sie keine Konstruktoren verwenden können.

Ich habe ein RoadNetwork-Skript, das einen Verweis auf RoadNodes und RoadCurves enthält, die beide RoadNetwork über einen Singleton lokalisieren und sich selbst registrieren/abmelden. Ich habe "Mini-Fabriken" in RoadNode und RoadCurve eingerichtet, die sich die Mühe machen, sich mit einem Spielobjekt zu verbinden.

RoadNode erste Kontrollen mit RoadNetwork um sicherzustellen, dass bei der gleichen Position bereits ein Knoten gibt es nicht, durch dies zu tun:

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

Wo die entsprechende Methode in RoadNetwork ist:

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

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

tempList war ein Versuch, das Problem einzugrenzen, aber ich bekomme genau den gleichen Fehler. Es sollte "Nodes.Single (...", aber ich bezweifle, dass es wichtig ist. Ich bekomme den gleichen Fehler, wenn ich die Linq-Abfrage direkt in der New() -Methode aufrufen.

Also ja, diese Ausnahme löst und Punkte ich zu diesem tempList.Single() Linie. Was wäre der Grund sein?

Antwort

13

someEnumerable.Single(...) eine Ausnahme auslöst, wenn es nicht genau ein Element in someEnumerable ist. Vorausgesetzt, dass Sie nur tempList erklären eine leere Liste sein, es wird immer werfen eine Ausnahme

Wenn Sie null abrufen möchten, wenn keine Elemente vorhanden sind, verwenden Sie SingleOrDefault. (Dies wird immer noch eine Ausnahme auslösen, wenn das Aufzählungszeichen mehr als ein Element enthält.) Wenn Sie das erste Element mögen, so dass Ihr enumerable beliebige Anzahl von Elementen enthalten darf, verwenden First (löst eine Ausnahme aus, wenn die zählbaren keine Elemente enthält) oder FirstOrDefault (gibt null in der Fall).

Wenn Sie schließlich prüfen möchten, ob Elemente einer Liste mit einem gegebenen Prädikat übereinstimmen, verwenden Sie .

+0

Dank, ich habe nicht etwas davon wissen, aber das ist nicht der Fehler (Ich würde eine Nullreferenz bekommen).Es ist, dass die Sammlung aus irgendeinem Grund aufgrund ihres Zustands nicht gültig ist. –

+3

Es ist ziemlich schwierig, Ihnen zu helfen, wenn Sie nicht den genauen Fehler posten. Laut http://msdn.microsoft.com/en-us/library/bb155325.aspx ist das Ergebnis der Verwendung von 'Single' in einem Enumerable mit nicht genau einem Element eine' InvalidOperationException', keine Art von NULL-Verweis Ausnahme. – Domenic

+0

Ich möchte nur sagen, dass die "OrDefault" Versionen für meine spezielle Situation funktionierten. Ich verwende auch Unity und ich erhielt dieselbe InvalidOperation-Ausnahme. In meinem Fall benutzte ich 'collection.First()' in LINQ. Das Ändern zu '.FirstOrDefault' hat es behoben. Die "OrDefault" -Versionen der LINQ-Methoden sind immer eine sichere Wette, wie es scheint. – Aaron

0

Ich denke, was Domenic sagen wollte war, dass .Single() einen Fehler auslöst, wenn mehr als ein Element mit Ihrem Prädikat übereinstimmt. Ihre Sammlung someEnumerable muss doppelte Kopien von jedem einzelnen Singleton (nicht dem Programmiermuster) enthalten, das Sie abrufen möchten.

0

Es scheint, dass es ein Problem mit der Art gibt, wie Sie das Singleton-Muster in Unity implementieren. Wenn Sie beim Überprüfen einer Liste eine NULL-Verweisausnahme erhalten, die bedeutet, dass die Liste nicht initialisiert wurde, wird der Singleton wahrscheinlich nicht instanziiert, oder Sie greifen nicht auf den Singleton zu, den Sie instanziiert haben.

ich in der Regel einen Singleton MonoBehaviour zu einem Gameobject angebracht verwenden, und initialisiert, wie dies beim ersten Zugriff instanziiert:

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