2017-05-05 33 views
5

私はUnityを使用しています。 IEnumerable.Select()を使用して、タイプのリストを取得し、それらを(コンポーネントとして)GameObjectに追加します。この実行 :newObjectsが一つだけの参照を含んでいるがC# - LINQ Select()関数を2回呼び出します。

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

は実際には、当該ゲームオブジェクトにコンポーネントの同じタイプのを加算します。作成されたもう1つのコンポーネントは、参照を返さずに浮遊します。

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

ワークス、唯一のゲームオブジェクトに各コンポーネントタイプのいずれかを追加します。 はこれを実行します。しかし、それはちょっと醜いように見えます。 (IGameManagerは、問題のすべての種類のインターフェイスを実装しています)

foreachループを使用することはできますが、それは完全に雄弁ではなく、この動作を説明するオンライン記事を見つけることができず、私の好奇心私の方が良くなっています。

私の質問は、Select()は指定された関数を入力ごとに2回呼び出しますが、結果データのコピーは1つだけ返すのはなぜですか?そして、どのように私はこの動作を修正/防止/補償するのですか?

ありがとうございます!

+2

types.Select(トン=>(IGameManager)gameObject.AddComponent(t))のToListメソッド()。 – loneshark99

+2

'Select()'は提供されたデリゲートを呼び出さない。これは、遅延実行された 'IEnumerable'オブジェクトのみを構築します。結果の 'IEnumerable'オブジェクトを列挙するたびにデリゲートが呼び出されます。 – PetSerAl

答えて

8

あなたが使用している周囲のコードを提供していません。実際に与えられた行は、その時点では何もしません。評価されず、式ツリーだけが設定されます。

あなたのコードでいくつかの自由を取り、あなたが式ツリーを作成したあなたのコード、あなたはそれで何かをするたびにゲームオブジェクト

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 

上のコンポーネントに得ることができると仮定すると、そのトリガーに行きますその中の表現。私はこれがあなたに起こっていることを推測しています。ここで私のコードで見ることができますカウントを求めるたびに、あなたはあなたのgameobjectsでより多くのオブジェクトを取得します。これを避けるために

、そのようなリストや配列にそれを回すことで、一度それを評価: -

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

これはまさに上記の私のコメントです。 – loneshark99

+1

@ loneshark99うん、そうです。しかし、それはちょうど最後の行です、質問自体は "理由"を聞いていた –

+0

@KeithNicholas – loneshark99

関連する問題