I've been playing around with XNA a lot lately and I've also been reading quite a bit about garbage collection in games. I think I've done a reasonable job of reducing the amount of garbage by using pooling and avoiding a dependence on foreach.
Right now I have my base game entities stored in a KeyedCollection that allows me to iterate over all entities (like a List) and reference an entity by key (like a Dictionary).
I would like to be able to query my collection and return another collection without producing garbage each query. I've included a sample of the concept below because I think I'm better at coding them I am at explaining...
/// <summary>
/// Defines a sample entity.
/// </summary>
public class SampleEntity
{
public uint Id;
public Vector2 Position;
}
/// <summary>
/// Defines a collection of sample entities.
/// </summary>
public class EntityCollection : KeyedCollection<uint, SampleEntity>
{
/// <summary>
/// Return the key for the supplied item.
/// </summary>
protected override uint GetKeyForItem(SampleEntity item)
{
return item.Id;
}
}
/// <summary>
/// Defines the sample game class.
/// </summary>
public class GameSample
{
/// <summary>
/// Create a new instance of the GameSample class.
/// </summary>
public GameSample()
{
Entities = new EntityCollection();
}
/// <summary>
/// Get the collection of game entities.
/// </summary>
public EntityCollection Entities { get; private set; }
/// <summary>
/// Return the collection of entities within a radius of the supplied point.
/// </summary>
public List<SampleEntity> Query(Vector2 center, float radius)
{
List<SampleEntity> results = new List<SampleEntity>() // BAD, BAD, BAD!!!!!
//
// add the entities to the results collection
//
return results;
}
}
This (overly simplified) example would produce a heck of a lot of garbage because it creates a new List object every call. I've also played with creating a global results list and clearing every call but that seems ugly.
/// <summary>
/// Return the collection of entities within a radius of the specified point.
/// </summary>
public List<SampleEntity> Query(Vector2 center, float radius)
{
_globalResults.Clear();
//
// add the entities to the global results collection
//
return _globalResults;
}
Am I just missing something? Is there a more elegant solution out there I'm just not aware of.