2017-05-05 80 views
5

Używam Unity. Używam IEnumerable.Select(), aby wziąć listę typów i dodać je (jako komponenty) do GameObject. Running to:C# - LINQ Select() wywołuje funkcję dwa razy

var newObjects = types.Select(t => (IGameManager)gameObject.AddComponent(t)); 

Właściwie dodaje dwa tego samego typu elementów do GameObject mowa, chociaż newObjects zawiera tylko odniesienie do jednego. Drugi stworzony komponent po prostu się unosi, bez zwracania referencji. Running to:

foreach(var t in types) 
{ 
    newObjects.Add((IGameManager)gameObject.AddComponent(t)); 
} 

Works, a jedynie dodaje jeden z każdego rodzaju części do GameObject. Ale wygląda trochę brzydko. (IGameManager to interfejs wszystkich typów, których dotyczy implementacja).

Mogę po prostu użyć pętli foreach, ale to nie jest całkowicie wymowne, a poza tym nie mogę znaleźć żadnych artykułów online wyjaśniających to zachowanie, a tym samym moją ciekawość jest coraz lepszy ode mnie.

Moje pytanie brzmi: dlaczego funkcja Select() wywołuje określoną funkcję dwukrotnie na jedno wejście, a zwraca tylko jedną kopię wynikowych danych? I jak mogę naprawić/zapobiec/zrekompensować to zachowanie?

Dzięki!

+2

types.Select (T => (IGameManager) gameObject.AddComponent (t)) ToList() – loneshark99

+2

'Wybierz()' nie wywołuje podanego delegata. Tworzy tylko odroczony wykonany obiekt 'IEnumerable'. I delegate będzie wywoływane za każdym razem, gdy wyliczysz wynikowy obiekt 'IEnumerable'. – PetSerAl

Odpowiedz

8

Nie podałeś otaczającego kodu w miejscu, w którym go używasz, linia, którą podasz, faktycznie nic nie robi w tym momencie, nic nie jest oceniane, tylko drzewo wyrażeń jest ustawione.

przyjmowanie niektórych swobód z kodem i zakładając, że można dostać się do elementów na GameObject

var gameObject = new GameObject(); 
var types = new List<string>() { "a", "b", "c" }; 
var newObjects = types.Select(t => (IGameManager)gameObject.AddComponent(t)); 
// at this point, nothing has happened.... 
Console.WriteLine(gameObject.Components.Count()); // 0 
Console.WriteLine(newObjects.Count()); // 3 - we trigger the selects 
Console.WriteLine(gameObject.Components.Count()); // 3 
Console.WriteLine(newObjects.Count()); // 3 - we trigger the selects again 
Console.WriteLine(gameObject.Components.Count()); // 6 

o utworzeniu drzewa wyrażenie kodu, za każdym razem coś zrobić z nią, jej będzie wyzwalać wyrażenia w nim zawarte. Zgaduję, że to właśnie się z tobą dzieje. Możesz zobaczyć tutaj w moim kodzie, że za każdym razem gdy pytasz o liczbę, dostajesz więcej obiektów w swoich obiektach gry.

Aby tego uniknąć, należy ocenić go raz, obracając go do listy lub tablicy tak: -.

var newObjects = types.Select(t => (IGameManager)gameObject.AddComponent(t)).ToList(); 
+0

to jest dokładnie mój komentarz powyżej. – loneshark99

+1

@ loneshark99 tak, więc tak jest. Ale to tylko ostatnia linijka, samo pytanie brzmiało: "Dlaczego" –

+0

zrozumiałem, że @KeithNicholas – loneshark99