Is it possible to save a Type (using "typeof()") in an enum?
C#TypesEnumsType ConversionC# Problem Overview
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!
C# Solutions
Solution 1 - C#
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.
Solution 2 - C#
This is not exactly what u are asking for. I find Jon's attribute method the best. But why not wrap it in an extension method?
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);
}
}
And call it:
PowerupEffectType e = PowerupEffectType.WATER;
var t = e.GetPowerupEffectType();
Solution 3 - C#
How about something like this?
You get the type-safety that you do with an enum, plus implicit conversion to 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));
}
Solution 4 - C#
You could use a static Dictionary<PowerupEffectType, Powerup>
. I believe that would be the kind of "marriage" you are looking for. It would allow easy enumeration and access.
Solution 5 - C#
You could use only numeric types as by documentation of Microsoft. By default the underlying type of each element in the enum is int. You can specify another integral numeric type by using a colon, as shown in the previous example. For a full list of possible types, see enum. Reference: Enumeration Types
Solution 6 - C#
Sorry, I don't quite follow this, what are you actually trying to achieve; could you give a code excerpt? I'm not sure why you can't just use inheritance here and what an enumeration gives you that type inheritance doesn't. It feels to me like you're presenting the solution rather than the problem, I may be completely wrong, could you clarify how you're planning to use this meta-information?
I'm confused, are you asking for something that tells you the type of an instance of a type/class? You can use an enumeration to store a list of the types of each type that you say, but why do you want to? You say you don't want to have the other programmers use switch statements, but I'm sorry I can't see what benefit you're getting from storing the type information in some enumeration of... the type. Every instance knows what type it is and what it can do.
What will you do with the type information? If the types all inherit from a base type, then presumably they have common functionality that can be specified in an abstract
method for any special-case handling, or perhaps return a Null Object
where there's nothing to do (or maybe just do nothing). This way you don't need to worry about adding new classes- as they must have the necessary behaviour. I try to avoid Enum
s except in situations where you're actually enumerating a fixed set of arbitrary values, they are inflexible. Enum
s have to be maintained, which is very difficult (in practice).
Solution 7 - C#
I actually think you might want to take a look at a dependency injection framework.
It looks like you are trying to have other developers work on different components and then you are trying to integrate them all at the end in one central location in the code base.
A few projects to look at: