我使用Unity。我使用IEnumerable.Select()获取类型列表并将它们(作为组件)添加到GameObject。 运行这个:
var newObjects = types.Select(t => (IGameManager)gameObject.AddComponent(t));
实际上将相同类型组件的两个添加到相关游戏对象中,尽管newObjects仅包含对一个的引用。另一个创建的组件只是浮动,而不返回引用。 运行这个:
foreach(var t in types)
{
newObjects.Add((IGameManager)gameObject.AddComponent(t));
}
Works,并且只向GameObject添加每种组件类型中的一种。但是,它看起来有点难看。 (IGameManager是所有类型的接口实现的接口。)
我可以使用foreach循环,但这不完全是雄辩的,而且,我无法在网上找到任何解释这种行为的文章,因此我的好奇心越来越好。
所以,我的问题是:为什么Select()每次输入调用指定的函数两次,但只返回结果数据的一个副本?我该如何修复/预防/补偿这种行为?
谢谢!
答案 0 :(得分:10)
您还没有提供使用它的周围代码,您提供的行实际上并没有做任何事情,没有评估任何内容,只是设置了表达式树。
对您的代码采取一些自由,并假设您可以访问游戏对象上的组件
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
使用您的代码,您已经创建了一个表达式树,每次使用它时,它都会触发其中的表达式。我猜这是发生在你身上的事。您可以在我的代码中看到,每次您要求计数时,您都会在游戏对象中获得更多对象。
为了避免这种情况,可以通过将其转换为如下所示的列表或数组来评估它: -
var newObjects = types.Select(t => (IGameManager)gameObject.AddComponent(t)).ToList();