Home > Back-end >  Is it possible to provide a variable Enumerated Type as a parameter to a C# method
Is it possible to provide a variable Enumerated Type as a parameter to a C# method

Time:12-28

I apologise if this is a dumb question! I presently have several different methods to funnel selection into a generic Spawn method, called by different enumerated types to access different arrays of objects:

Prefab[] shipPrefabs;
Prefab[] rockPrefabs;
Prefab[] alienPrefabs;
Prefab[] shotPrefabs;

enum SHIP_TYPE{}
enum ROCK_TYPE{}
enum ALIEN_TYPE{}
enum SHOT_TYPE{}

void Spawn(SHIP_TYPE, ...) { Spawn(shipPrefabs[(int)SHIP_TYPE]); }
void Spawn(ROCK_TYPE, ...) { Spawn(rockPrefabs[(int)ROCK_TYPE]); }
void Spawn(ALIEN_TYPE, ...) { Spawn(alienPrefabs[(int)ALIEN_TYPE]); }
void Spawn(SHOT_TYPE, ...) { Spawn(shotPrefabs[(int)SHOT_TYPE]); }

void Spawn(Prefab) { create object, yada yada }

I'd like to be able to create a more generalised Spawn method that can take a variable enum parameter and process it accordingly based on enum type, something conceptually like:

void Spawn(var OBJ_TYPE, ...) {
    Prefab newObject;
    switch(OBJ_TYPE){
        case SHIP_TYPE: newObject = shipPrefabs[(int)OBJ_TYPE]);  break;
        case ROCK_TYPE: newObject = rockPrefabs[(int)OBJ_TYPE]);  break;
        case ALIEN_TYPE: newObject = alienPrefabs[(int)OBJ_TYPE]);  break;
        case SHOT_TYPE: newObject = shotPrefabs[(int)OBJ_TYPE]);  break;
    }

    create newObject, yada yada
}

I've tried things like 'typeof' and 'is' which tells me what the parameter is, but I can't 'cast' it into a value I can work with.

Is it possible to do what I'm trying?

CodePudding user response:

In general I would rather keep your first approach of using an overloaded method and do not invent ways around the hard typing in c#.

Runtime type checks are always slower and error prone.


However, using a type switch you can totally do what you tried just with a few modifications.

The generic enum type you were looking for is System.Enum

void Spawn(Enum OBJ_TYPE, ...) 
{
    Prefab newObject = null;

    switch(OBJ_TYPE)
    {
        // This also directly includes the type cast
        case SHIP_TYPE shipType: 
            newObject = shipPrefabs[(int) shipType]);  
            break;

        case ROCK_TYPE rockType: 
            newObject = rockPrefabs[(int)rockType]); 
            break;

        case ALIEN_TYPE alienType: 
            newObject = alienPrefabs[(int) alienType]); 
            break;

        case SHOT_TYPE shotType: 
            newObject = shotPrefabs[(int) shotType]); 
            break;

        default:
            throw new ArgumentException($"Enum {OBJ_TYPE} of unsupported type {OBJ_TYPE.GetType().FullName} ");
    }

    // create newObject, yada yada
}

The included type cast to the according enum is probably even redundant if you don't do anything further with it since you then cast to int anyway which should be the same value as simply directly using (int)OBJ_TYPE

NOTE though: As said on the top of the answer, this can now possibly be used with just any enum value which is of course a lot more error prone then using overloads.

CodePudding user response:

Something like this maybe?

void Spawn(System.Enum otype, ...) {
    Prefab newObject;
    if (otype.GetType() == typeof(SHIP_TYPE))
        newObject = shipPrefabs[(int)otype]);
    else if (otype.GetType() == typeof(ROCK_TYPE))
        newObject = rockPrefabs[(int)otype]);
    else if (otype.GetType() == typeof(ALIEN_TYPE))
        newObject = alienPrefabs[(int)otype]);
    else if (otype.GetType() == typeof(SHOT_TYPE))
        newObject = shotPrefabs[(int)otype]);

    create newObject, yada yada
}

One thing, you can not use switch for this, as it does not see typeof as constant. I am not sure you can overcome this.

Whether it is a good design approach or not is another question.

CodePudding user response:

As nested enums are not permitted, a cool way using multiple enums and overloading can be this:

        GameObject[] shipPrefabs;
        GameObject[] rockPrefabs;
        GameObject[] alienPrefabs;
        GameObject[] shotPrefabs;

        GameObject[][] goArray = new GameObject[][] {
            new GameObject[4],
            new GameObject[4],
            new GameObject[4],
            new GameObject[4],
        };

        private void Start() {
            goArray[0] = shipPrefabs;
            goArray[1] = rockPrefabs;
            goArray[2] = alienPrefabs;
            goArray[3] = shotPrefabs;
        }

        enum ObjType {
            SHIP_TYPE,
            ROCK_TYPE,
            ALIEN_TYPE,
            SHOT_TYPE,
        }

        enum ShipType { 
            a, b, c, d
        }
        enum RockType {
            e, f, g, h
        }
        enum AlienType {
            i, j, k, m
        }
        enum ShotType {
            n, o, p, q
        }

        void Spawn(GameObject go) { }

        void Spawn(ObjType objType, ShipType shipType) {
            Spawn(goArray[(int)objType][(int)shipType]);
        }
        void Spawn(ObjType objType, RockType rockType) {
            Spawn(goArray[(int)objType][(int)rockType]);
        }
        void Spawn(ObjType objType, AlienType alienType) {
            Spawn(goArray[(int)objType][(int)alienType]);
        }
        void Spawn(ObjType objType, ShotType shotType) {
            Spawn(goArray[(int)objType][(int)shotType]);
        }
  • Related