Best type-conversion questions in June 2012

C# - Is it possible to save a Type (using "typeof()") in an enum?

47 votes

So I'm creating a game in XNA, C# 4.0, and I need to manage a lot of PowerUps (which in code are all inherited from class "PowerUp"), and to handle back-end management of the PowerUps I currently have an enum, PowerupEffectType, with a value for each child class of PowerUp. Eventually in the code I need to do conversions from PowerupEffectType to the Powerup type (of class Type, achieved usually with typeof([class name])).

Since this is a group project, I want to marry each value of PowerupEffectType to its corresponding class Type as well as possible, i.e.: Not just expect my other programmers to use switch statements to do the conversion manually, and making sure additions/expansions later involve as few changes in as few places as possible. I have a few options for this, and the best I've discovered so far is creating enum pseudo-methods that condense everything down to a single switch statement (99% of what I want), thanks to some tips I found here: http://msdn.microsoft.com/en-us/library/bb383974.aspx

But I'm trying to take it one step further - can I save a Type in an enum? I know you can save enums as a specific type (link: http://msdn.microsoft.com/en-us/library/cc138362.aspx), but Type isn't one of them. The current choices are byte, sbyte, short, ushort, int, uint, long, and ulong. Is there any feasible way to save a convert a Type to any of the above data types and back?

Just to be clear, this is what I WISH I could do, and I'm looking for a way to do:

// (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)
}

Is there any way to do this, or am I just overcomplicating a solution to a problem that's already 99% complete?

Thanks in advance!

You can't do it as the value of an enum, but you could specify it in an attribute:

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
}

You can then extract those attribute values at execution time with reflection. However, I would personally just create a dictionary:

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

No need for a special attribute, no need to extract the values with fiddly reflection code.