2010-10-13 26 views
5

Cette erreur est levée lors de l'exécution d'une requête Linq sur une liste. J'utilise Unity3D 3.0 avec C# (Unity3D utilise Mono 2.6). Unity3D, pour autant que je sache, est monothread. Cela fonctionne en attachant des "scripts" (fichiers C# .cs) qui héritent d'un baseclass, à un "GameObject". En outre, Unity contrôle l'instanciation et la sérialisation des scripts afin que vous ne puissiez pas utiliser les constructeurs.L'opération n'est pas valide en raison de l'état actuel de l'objet - Linq on List

J'ai un script RoadNetwork qui contient une référence à RoadNodes et RoadCurves, qui localisent RoadNetwork via un singleton et s'enregistrent/se désinscrivent. J'ai mis "mini-usines" dans RoadNode et RoadCurve qui font le dur travail de se brancher à un gameobject.

RoadNode vérifie d'abord avec RéseauRoutier pour vous assurer qu'il isnt déjà un nœud à cette même position, en faisant ceci:

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

Lorsque la méthode appropriée RéseauRoutier est:

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

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

tempList était une tentative de réduire le problème mais j'obtiens précisément la même erreur. Il devrait être "Nodes.Single (...", mais je doute que cela ait de l'importance.J'ai la même erreur si j'appelle la requête Linq directement dans la méthode New()

Alors oui, cette Exception jette et pointe moi à cette ligne tempList.Single(). Qu'est-ce que la raison pour être?

Répondre

13

someEnumerable.Single(...) lève une exception s'il n'y a pas un seul élément de someEnumerable. Étant donné que vous venez de déclarer tempList être une liste vide, il sera toujours jeter une exception

Si vous souhaitez récupérer null s'il n'y a pas d'éléments, utilisez SingleOrDefault (cela lèvera quand même une exception si l'énumérable contient plus d'un élément.) Si vous voulez que le premier élément, de sorte que votre dénombrable est autorisé à contenir un certain nombre d'éléments, utilisez First (lève une exception si la dénombrable ne contient aucun élément) ou FirstOrDefault (retourne null dans l'affaire).

Enfin, si vous souhaitez simplement vérifier s'il existe des éléments d'une liste correspondant à un prédicat donné, utilisez Any.

+0

Merci, je ne savais pas certains, mais ce n'est pas l'erreur (j'aurais une référence nulle).C'est que la collection pour une raison quelconque n'est pas valide en raison de son état. –

+3

Il est assez difficile de vous aider si vous ne postez pas l'erreur exacte. En outre, selon http://msdn.microsoft.com/en-us/library/bb155325.aspx le résultat de l'utilisation de 'Single' sur un énumérable avec pas exactement un élément est une' InvalidOperationException', pas n'importe quel type de référence nulle exception. – Domenic

+0

Je veux juste dire que les versions "OrDefault" ont fonctionné pour ma situation particulière. J'utilise également Unity et je recevais la même exception InvalidOperation. Dans mon cas, j'utilisais 'collection.First()' dans LINQ. Changer cela en '.FirstOrDefault' le corrige. Les versions "OrDefault" des méthodes LINQ sont toujours un pari sûr. – Aaron

0

Je pense que Domenic voulait dire que .Single() renvoie une erreur lorsque plus d'un élément correspond à votre prédicat. Votre collection someEnumerable doit contenir des copies de n'importe quel singleton (pas le modèle de programmation) que vous essayez de récupérer.

0

Il semble qu'il y ait un problème avec la façon dont vous implémentez le motif singleton dans Unity. Si vous obtenez une exception de référence nulle lors de la vérification d'une liste qui signifie que la liste n'a pas été initialisée, vous n'instanciez probablement pas le singleton ou vous n'accédez pas au singleton que vous avez instancié.

J'utilise habituellement un MonoBehaviour singleton attaché à un gameobject qui instancie et initialise du premier accès comme celui-ci:

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