-2

I'm writing a simple networking system. Entities are defined as classes derived from the base class Entity. In order to identify entities over the network, I have a unique ID for each one, but when it comes time to spawn a new entity, I need a way to identify which entity type (and therefore which class) to create, so I also store a typeId for each entity.

public abstract class Entity
{
    uint id;
    ushort typeId;
    //abstract stuff
}
public class Entity_BeachBall : Entity
{
    //overridden stuff
}

Say I have a list of all the derived entity classes like so:

    public List<Type> entityTypes = new List<Type>
    {
        typeof(Entity_BeachBall)
    };

Now I have a way to identify which class an entity uses; for instance, if typeId == 0, then that means it should use the class Entity_BeachBall. The problem is, how can I create a new instance of that class, even if it gets immediately implicitly cast back to the base class?

This is roughly what I want to do:

public static class EntityManager
{
    public List<Type> entityTypes = new List<Type>
    {
        typeof(Entity_BeachBall)
    };
    
    public Entity GetNewEntity(ushort typeId)
    {
        return new entityTypes[typeId](); //something like this
    }
}

Is this possible? If not, is there a better solution?

Clonkex
  • 3,373
  • 7
  • 38
  • 55
  • Why downvote? Doesn't the fact that it got a unique and good answer disqualify it from the "not useful" criterium of downvoting? – Clonkex Mar 09 '21 at 01:58

1 Answers1

1

Don't use this approach at all.

Instead, consider creating a dictionary of factory delegates, keyed by type Id. Notice how we use a dictionary instead of a list so as to not rely on incidental and brittle correlations between type Ids and list positions.

private static readonly Dictionary<ushort, Func<Entity>> entityFactories = new()
{
    [0] = () => new Entity_BeachBall(),
    // etc.
};

public static Entity GetNewEntity(ushort typeId)
{  
    if (!entityFactories.ContainsKey(typeId))
    {
        throw new ArgumentException($"Unknown typeId {typeId}", nameof(typeId));
    }

    return entityFactories[typeId]();
}

Alternatively you can just use pattern matching

public static Entity GetNewEntity(ushort typeId)
{
    return typeId switch
    {
        0 => new Entity_BeachBall(),
        // etc.
        _ => throw new ArgumentException($"Unknown typeId {typeId}", nameof(typeId))
    };
}
Aluan Haddad
  • 29,886
  • 8
  • 72
  • 84