当我提取一个元素时,c# List 的数组是否被移动?
Is c# List's array being shifted when i extract an element?
我在 Unity 中为任何游戏对象实现了一个通用池系统。
当我从 List<> 中删除一个 GameObject 时,我总是取最后一个以避免移动 List 实现中使用的数组。没有在互联网上找到任何有用的东西,所以试图自己弄清楚。
那有用还是我只是在做无用的代码?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolSystem : MonoBehaviour
{
public static Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();
#region cached
private static GameObject lastReturned;
#endregion
public static GameObject GetElementFromPool(GameObject g)
{
if (!pool.ContainsKey(g.name))
{
lastReturned = Instantiate(g) as GameObject;
pool.Add(g.name, new List<GameObject>());
lastReturned.name = g.name;
return lastReturned;
}
if (pool[g.name].Count == 0)
{
lastReturned = Instantiate(g) as GameObject;
lastReturned.name = g.name;
}
else
{
lastReturned = pool[g.name][pool[g.name].Count - 1];
pool[g.name].RemoveAt(pool[g.name].Count - 1);
}
return lastReturned;
}
public static void AddToPool(GameObject g)
{
if (!pool.ContainsKey(g.name))
{
pool.Add(g.name, new List<GameObject>());
}
pool[g.name].Add(g);
}
}
我在回答和评论中添加了所有建议,感谢大家的帮助。在下面添加更改的代码,也许有人会发现它有用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolSystem : MonoBehaviour
{
public static Dictionary<string, Stack<GameObject>> pool = new Dictionary<string, Stack<GameObject>>();
#region cached
private static GameObject lastReturned;
private static Stack<GameObject> lastUsedStack;
#endregion
public static GameObject GetElementFromPool(GameObject g)
{
if (pool.TryGetValue(g.name, out lastUsedStack))
{
if (pool[g.name].Count == 0)
{
lastReturned = Instantiate(g) as GameObject;
lastReturned.name = g.name;
}
else
{
lastReturned = pool[g.name].Pop();
}
}
else
{
lastReturned = Instantiate(g) as GameObject;
pool.Add(g.name, new Stack<GameObject>());
lastReturned.name = g.name;
return lastReturned;
}
return lastReturned;
}
public static void AddToPool(GameObject g)
{
if (!pool.ContainsKey(g.name))
{
pool.Add(g.name, new Stack<GameObject>());
}
pool[g.name].Push(g);
}
}
When you call RemoveAt to remove an item, the remaining items in the list are renumbered to replace the removed item. For example, if you remove the item at index 3, the item at index 4 is moved to the 3 position. In addition, the number of items in the list (as represented by the Count property) is reduced by 1.
This method is an O(n) operation, where n is (Count - index).
所有索引集合都有这个 属性。如果您在任何时候删除一个元素,则所有后续元素都会向上移动。这是您找不到 ConcurrentList[T]
的一个重要原因。制作一个只会让您首先进入索引竞争条件。如果不考虑使用代码,就不可能使 List 并发。
Keyd 集合 (Dictionary[int, GameObject]
) 没有这个缺点。请注意,某些操作有特殊的集合。 Queue(先进先出)和Stack(先进后出)。这些可能更适合您的场景。
我在 Unity 中为任何游戏对象实现了一个通用池系统。 当我从 List<> 中删除一个 GameObject 时,我总是取最后一个以避免移动 List 实现中使用的数组。没有在互联网上找到任何有用的东西,所以试图自己弄清楚。 那有用还是我只是在做无用的代码?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolSystem : MonoBehaviour
{
public static Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();
#region cached
private static GameObject lastReturned;
#endregion
public static GameObject GetElementFromPool(GameObject g)
{
if (!pool.ContainsKey(g.name))
{
lastReturned = Instantiate(g) as GameObject;
pool.Add(g.name, new List<GameObject>());
lastReturned.name = g.name;
return lastReturned;
}
if (pool[g.name].Count == 0)
{
lastReturned = Instantiate(g) as GameObject;
lastReturned.name = g.name;
}
else
{
lastReturned = pool[g.name][pool[g.name].Count - 1];
pool[g.name].RemoveAt(pool[g.name].Count - 1);
}
return lastReturned;
}
public static void AddToPool(GameObject g)
{
if (!pool.ContainsKey(g.name))
{
pool.Add(g.name, new List<GameObject>());
}
pool[g.name].Add(g);
}
}
我在回答和评论中添加了所有建议,感谢大家的帮助。在下面添加更改的代码,也许有人会发现它有用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolSystem : MonoBehaviour
{
public static Dictionary<string, Stack<GameObject>> pool = new Dictionary<string, Stack<GameObject>>();
#region cached
private static GameObject lastReturned;
private static Stack<GameObject> lastUsedStack;
#endregion
public static GameObject GetElementFromPool(GameObject g)
{
if (pool.TryGetValue(g.name, out lastUsedStack))
{
if (pool[g.name].Count == 0)
{
lastReturned = Instantiate(g) as GameObject;
lastReturned.name = g.name;
}
else
{
lastReturned = pool[g.name].Pop();
}
}
else
{
lastReturned = Instantiate(g) as GameObject;
pool.Add(g.name, new Stack<GameObject>());
lastReturned.name = g.name;
return lastReturned;
}
return lastReturned;
}
public static void AddToPool(GameObject g)
{
if (!pool.ContainsKey(g.name))
{
pool.Add(g.name, new Stack<GameObject>());
}
pool[g.name].Push(g);
}
}
When you call RemoveAt to remove an item, the remaining items in the list are renumbered to replace the removed item. For example, if you remove the item at index 3, the item at index 4 is moved to the 3 position. In addition, the number of items in the list (as represented by the Count property) is reduced by 1.
This method is an O(n) operation, where n is (Count - index).
所有索引集合都有这个 属性。如果您在任何时候删除一个元素,则所有后续元素都会向上移动。这是您找不到 ConcurrentList[T]
的一个重要原因。制作一个只会让您首先进入索引竞争条件。如果不考虑使用代码,就不可能使 List 并发。
Keyd 集合 (Dictionary[int, GameObject]
) 没有这个缺点。请注意,某些操作有特殊的集合。 Queue(先进先出)和Stack(先进后出)。这些可能更适合您的场景。