[C#] Action et passage de paramètres

a marqué ce sujet comme résolu.

Bonjour à tous,

Il y a quelque chose que je ne comprends pas avec les actions, c’est la valeur des paramètres. Comment faire pour que la valeur des paramètres soit fixée au moment de la déclaration de l’action, ou continue de dépendre de la variable donnée ?

Par exemple :

int id = 4;
mybutton.clicked += new System.Action(() => { ChangeViewType(id); });
id = 10;

Comment faire pour que le paramètre passé lors de la déclaration reste fixe (4) et ne se modifie pas en 10 lorsque id = 10 ?

Bizarrement, lorsque j’écris ce code :

  foreach (VisualElement b in list)
  {
      if (b.GetType().ToString() == "UnityEngine.UIElements.Button")
      {
          buttonViewList.Add(root.Q<Button>(b.name));
          buttonViewList[buttonViewList.Count - 1].clicked += new System.Action(() => { ChangeViewType(b.name); });
      }
  }

Lorsque j’appuie sur un bouton quand je lance l’application, j’obtiens le bon nom de bouton à chaque fois.

En revanche, avec ce code :

  for(int i = 0; i < list.Count; i++)
  {
      if (list[i].GetType().ToString() == "UnityEngine.UIElements.Button")
      {
          buttonViewList.Add(root.Q<Button>(list[i].name));
          buttonViewList[buttonViewList.Count - 1].clicked += new System.Action(() => { ChangeViewType(list[i].name); });
      }
  }

Là l’application plante quand j’appuie sur un bouton, parce que l’action appelle list[i].name avec i = 3.

On dirait donc que dans le premier cas la valeur du paramètre est fixée, tandis que dans la seconde est continue d’être variable.

Merci par avance pour vos réponses !

En C#, les lambdas capturent les variables externes par "référence" même si ce n’est pas clairement explicité dans la documentation. En l’occurrence, dans ton dernier code d’exemple, le i est modifié à chaque tour. Pour remédier à ça, tu dois éventuellement créer une copie locale juste avant la fonction:

 for(int i = 0; i < list.Count; i++)
  {
      if (list[i].GetType().ToString() == "UnityEngine.UIElements.Button")
      {
          buttonViewList.Add(root.Q<Button>(list[i].name));
          int localI = i;
          buttonViewList[buttonViewList.Count - 1].clicked += new System.Action(() => { ChangeViewType(list[localI].name); });
      }
  }

Je m’étonne de ce qui est énoncé pour ce cas:

int id = 4;
mybutton.clicked += new System.Action(() => { ChangeViewType(id); });
id = 10;

id aura bien la valeur 10 après sa réassignation confere.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte