61 votes

Est-il possible d'enregistrer un Type (à l'aide de "typeof()") dans un enum?

Donc, je suis en train de créer un jeu avec XNA, C# 4.0, et je dois gérer beaucoup de Bonus (ce qui dans le code sont toutes héritées de la classe "mise sous tension"), et pour gérer le back-end de la gestion du Bonus j'ai actuellement un enum, PowerupEffectType, avec une valeur pour chaque enfant de la classe de mise sous tension. Finalement, dans le code que j'ai besoin de faire des conversions de PowerupEffectType à la mise sous tension de type (de la classe Type, atteint généralement avec typeof([class name])).

Puisque c'est un projet de groupe, je veux épouser chaque valeur de PowerupEffectType correspondant à son Type de classe aussi bien que possible, c'est à dire: ne Pas s'attendre mes autres programmeurs à utiliser les instructions switch pour faire la conversion manuellement, et de faire assurer les ajouts/extensions ultérieures comportent que peu de changements en peu d'endroits que possible. J'ai quelques options pour cela, et le meilleur que j'ai découvert à ce jour est la création d'enum pseudo-méthodes de condenser tout vers le bas à une seule instruction switch (99% de ce que je veux), grâce à quelques conseils que j'ai trouvé ici: http://msdn.microsoft.com/en-us/library/bb383974.aspx

Mais je suis en train de prendre une nouvelle étape - puis-je enregistrer un Type en enum? Je sais que vous pouvez enregistrer les énumérations comme un type spécifique (lien: http://msdn.microsoft.com/en-us/library/cc138362.aspx), mais Type n'est pas l'un d'eux. Les choix actuels sont octet, sbyte, short, ushort, int, uint, long, et ulong. Est-il possible d'enregistrer un convertir Type sur l'un de ces types de données et à l'arrière?

Juste pour être clair, c'est ce que je SOUHAITE que je pourrais faire, et je suis à la recherche d'un moyen de le faire:

// (Assuming 'LightningPowerup', 'FirePowerup', and 'WaterPowerup' are
// all declared classes that inherit from a single base class)

public enum PowerupEffectType
{
    LIGHTNING = typeof(LightningPowerup),
    FIRE = typeof(FirePowerup),
    WATER = typeof(WaterPowerup)
}

Est-il possible de le faire, ou je suis juste de compliquer à l'excès d'une solution à un problème qui est déjà 99%?

Merci à l'avance!

93voto

Jon Skeet Points 692016

Vous ne pouvez pas le faire tant que la valeur de l'enum, mais vous pouvez spécifier un attribut:

using System;
using System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Field)]
public class EffectTypeAttribute : Attribute
{
    public Type Type { get; private set; }

    public EffectTypeAttribute(Type type)
    {
        this.Type = type;
    }
}

public class LightningPowerup {}
public class FirePowerup {}
public class WaterPowerup {}

public enum PowerupEffectType
{
    [EffectType(typeof(LightningPowerup))]
    Lightning,
    [EffectType(typeof(FirePowerup))]
    Fire,
    [EffectType(typeof(WaterPowerup))]
    Water
}

Vous pouvez ensuite extraire ces valeurs d'attribut au moment de l'exécution avec la réflexion. Cependant, je serais personnellement, il suffit de créer un dictionnaire:

private static Dictionary<PowerupEffectType, Type> EffectTypeMapping =
    new Dictionary<PowerupEffectType, Type>
{
    { PowerupEffectType.Lightning, typeof(LightningPowerup) },
    { PowerupEffectType.Fire, typeof(FirePowerup) },
    { PowerupEffectType.Water, typeof(WaterPowerup) }
};

Pas besoin d'un attribut spécial, pas besoin d'extraire les valeurs avec fiddly code de réflexion.

18voto

nawfal Points 13500

Ce n'est pas exactement ce que tu demande. Je trouve Jon attribut méthode la meilleure. Mais pourquoi ne pas l'envelopper dans une méthode d'extension?

public Type GetPowerupEffectType(this PowerupEffectType powerEffect)
{
    switch (powerEffect)
    {
        case LIGHTNING:
            return typeof(LightningPowerup);
        case FIRE:
            return typeof(FirePowerup);
        case WATER:
            return typeof(WaterPowerup);
        default:
            return default(Type);
    }
}

Et de l'appeler:

PowerupEffectType e = PowerupEffectType.WATER;
var t = e.GetPowerupEffectType();

16voto

mlorbetske Points 3735

Comment quelque chose comme cela?

Vous obtenez le type de sécurité que vous faites avec un enum, en plus de la conversion implicite de Type

public class PowerupEffectType
{
    private readonly Type _powerupType;

    public static implicit operator Type(PowerupEffectType powerupEffectType)
    {
        return powerupEffectType._powerupType;
    }

    private PowerupEffectType(Type powerupType)
    {
        _powerupType = powerupType;
    }

    public static readonly PowerupEffectType LIGHTNING = new PowerupEffectType(typeof(LightningPowerup));
    public static readonly PowerupEffectType FIRE = new PowerupEffectType(typeof(FirePowerup));
    public static readonly PowerupEffectType WATER = new PowerupEffectType(typeof(WaterPowerup));
}

9voto

benjer3 Points 389

Vous pouvez utiliser un static Dictionary<PowerupEffectType, Powerup>. Je crois que ce serait le genre de "mariage" vous êtes à la recherche pour. Il permet aisément de l'énumération et de l'accès.

2voto

Adil Points 80031

Vous pouvez utiliser uniquement les types numériques que par la documentation de Microsoft. Par défaut, le type sous-jacent de chaque élément de l'énumération est de type int. Vous pouvez spécifier une autre partie intégrante de type numérique à l'aide d'un colon, comme montré dans l'exemple précédent. Pour une liste complète des types possibles, voir enum. Référence: Énumération Des Types De

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X