Please notice I'm only showing for strings for it could be any type. In each case I mention how to extend it for more values if possible.
Using the enum as a key
You can use your enum type as a key for a dictionary (you want to be unique, so make it static and readonly in some helper class):
private static readonly Dictionary<MyEnum, string> _dict =
{
//Using dictionary initialization
{MyEnum.MyValue, "The text for MyValue"},
{MyEnum.MyOtherValue, "Some other text"},
{MyEnum.YetAnotherValue, "Something else"}
}
public static readonly Dictionary<MyEnum, string> Dict
{
get
{
return _dict;
}
}
And access the associated value:
string text = Dict[MyEnum.MyValue];
Or with:
string text;
if (Dict.TryGetValue(MyEnum.MyValue, out text))
{
//It has the value
}
else
{
//It doesn't have the value
}
This way you can access a string that is associated with the enum value. Then you can expose your Dictionary so that you can read the corresponding values.
You will need a complex type for storing more than one value. Just use your custom type isntead of string. Or if available you can use Tuples
.
Accesing the Dictionary
may mean an extra annoyance and hopefully it will not mean a threading problem too.
Enum.GetName
You can use Enum.GetName to read the name of the values of your enum:
string text = Enum.GetName(MyEnum.MyValue);
//text will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text = Enum.GetName(some);
Note: ToString()
should work too.
Sadly, this will not work for something else than the string.
Also it has the drawback that you cannot put any text there (it has to be a valid identifier).
Custom Attributes
You will have to declare an attribute type:
[AttributeUsage(AttributeTargets.Field)]
public class EnumValueAttribute : System.Attribute
{
public readonly string _value;
public string Value
{
get
{
return _value;
}
}
public EnumValueAttribute(string value) // value is a positional parameter
{
//beware: value can be null...
// ...but we don't want to throw exceptions here
_value = value;
}
}
Now you apply the attribute to your enum:
public enum MyEnum
{
[EnumValue("The text for MyValue")]
MyValue = 1,
[EnumValue("Some other text")]
MyOtherValue = 2,
[EnumValue("Something else")]
YetAnotherValue = 3
}
Lastly you will need to read the attribute back:
public static string GetValue(MyEnum enumValue)
{
FieldInfo fieldInfo = typeof(MyEnum).GetField(enumValue.ToString());
if (!ReferenceEquals(fieldInfo, null))
{
object[] attributes = fieldInfo.GetCustomAttributes(typeof(EnumValueAttribute), true);
if (!ReferenceEquals(attributes, null) && attributes.Length > 0)
{
return ((EnumValueAttribute)attributes[0]).Value;
}
}
//Not valid value or it didn't have the attribute
return null;
}
Now you can call it:
string text1 = GetValue(MyEnum.MyValue);
//text1 will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text2 = GetValue(some);
You can add more fields to your attribute class and use them to pass any other value you may need.
But this requires reflexion, and it may not be available if you are running in a sandbox. Also it will retrieve the attributes each time, creating some short lived objects in the proccess.
Emulate Enum
You can emulate an enum with a sealed class that has no public constructor and exposes static readonly instances of itself:
public sealed class MyEnumEmu
{
private static readonly string myValue = new MyEnumEmu("The text for MyValue");
private static readonly string myOtherValue = new MyEnumEmu("Some other text");
private static readonly string yetAnotherValue = new MyEnumEmu("Something else");
public static MyEnumEmu MyValue
{
get
{
return myValue;
}
}
public static MyEnumEmu MyOtherValue
{
get
{
return myOtherValue;
}
}
public static MyEnumEmu YetAnotherValue
{
get
{
return yetAnotherValue;
}
}
private string _value;
private MyEnumEmu(string value)
{
//Really, we are in control of the callers of this constructor...
//... but, just for good measure:
if (value == null)
{
throw new ArgumentNullException("value");
}
else
{
_value = value;
}
}
public string Value
{
get
{
return _value;
}
}
}
Use it as always:
var some = MyEnumEmu.MyValue;
And access the associated value:
string text = MyEnumEmu.MyValue.Value;
//text will have the text "MyValue"
//or
string text = some.Value;
This is the more flexible of all, you can either use a complex type instead of string or add extra fields for passing more than a single value.
But... it is not really an enum.