是否可以提供变量枚举类型作为 C# 方法的参数

Is it possible to provide a variable Enumerated Type as a parameter to a C# method

如果这是一个愚蠢的问题,我深表歉意!我目前有几种不同的方法将选择汇集到一个通用的 Spawn 方法中,由不同的枚举类型调用以访问不同的对象数组:

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 }

我希望能够创建一个更通用的 Spawn 方法,该方法可以采用可变枚举参数并根据枚举类型对其进行相应处理,概念上类似于:

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
}

我试过 'typeof' 和 'is' 之类的东西,它们告诉我参数是什么,但我不能 'cast' 把它变成我可以使用的值。

是否可以做我正在尝试的事情?

也许是这样的?

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
}

有一件事,你不能为此使用 switch,因为它不会将 typeof 视为常量。我不确定你能克服这个问题。

这是否是一个好的设计方法是另一个问题。

总的来说,我宁愿保留您使用重载方法的第一种方法,也不要在 c#.

中发明硬输入方法

运行时类型检查总是较慢且容易出错。


但是,使用类型开关,只需稍加修改,您就可以完全完成您尝试的操作。

您要查找的通用 enum 类型是 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
}

如果您不对其进行任何进一步的操作,则转换为相应 enum 的包含类型甚至可能是多余的,因为您随后转换为 int 无论如何它应该与简单的值相同直接使用 (int)OBJ_TYPE

但请注意:如答案顶部所述,现在可以仅与 any enum 值当然比使用重载更容易出错。

由于不允许嵌套枚举,使用多个枚举和重载的一种很酷的方法可以是:

        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]);
        }