tags:

views:

166

answers:

5

hi, there any way to define enum in c# like below?

public enum MyEnum : string
{
    EnGb = "en-gb",
    FaIr = "fa-ir",
    ...
}

ok, according to erick approach and link, i'm using this to check valid value from provided description:

public static bool IsValidDescription(string description)
    {
        var enumType = typeof(Culture);
        foreach (Enum val in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(val.ToString());
            AmbientValueAttribute[] attributes = (AmbientValueAttribute[])fi.GetCustomAttributes(typeof(AmbientValueAttribute), false);
            AmbientValueAttribute attr = attributes[0];
            if (attr.Value.ToString() == description)
                return true;
        }
        return false;
    }

any improvement?

+1  A: 

No. You can just use a Dictionary<String, String>. The type for an enum must be an integral type other than char. This is so they can be compared efficiently.

Matthew Flaschen
+2  A: 

If all your names/values are going to be exactly like that, you could just create an enum as normal.

public enum MyEnum
{
   EnGb
   FaIr
}

And then when you need the actual value, get the enum name as a string, make it lowercase and add a - in the middle.

string value = MyEnum.EnGb.ToString().ToLower().Insert(2, "-");
ho1
+4  A: 

Regarding Matthew's answer, I suggest you to use Dictionary<MyEnum, String>. I use it as a static property:

class MyClass
{
    private static readonly IDictionary<MyEnum, String> dic = new Dictionary<MyEnum, String>
    {
        { MyEnum.EnGb, "en-gb" },
        { MyEnum.RuRu, "ru-ru" },
        ...
    };

    public static IDictionary<MyEnum, String> Dic { get { return dic; } }
}
abatishchev
This is useful if the original values (`EnGb`, etc.) will be passed around the application. You should be careful with making the Dictionary getter public, though. Even though you have a `readonly` reference, the Dictionary itself is mutable.
Matthew Flaschen
@Matthew: Thanks for your tip! Here there are some workarounds: http://stackoverflow.com/questions/678379/is-there-a-read-only-generic-dictionary-available-in-net. Also another one w/o - to make property to be `internal`
abatishchev
+1  A: 

It is only possible indirectly by using attributes on the enum values, like so:

public enum MyEnum {
  [DefaultValue("en-gb")]
  EnGb,
  [DefaultValue("fa-ir")]
  FaIr,
  ...
}

You can then retrieve the string value using reflection by reading the custom attributes on the static fields of the enum.

Lucero
+6  A: 

Another alternative, not efficient but giving enum functionality is to use an attribute, like this:

public enum MyEnum
{
  [Description("en-gb")]
  EnGb,
  [Description("fa-ir")]
  FaIr,
  ...
}

And something like an extension method, here's what I use:

public static string GetDescription<T>(this T enumerationValue) where T : struct
{
  var type = enumerationValue.GetType();
  if (!type.IsEnum) throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
  var str = enumerationValue.ToString();
  var memberInfo = type.GetMember(str);
  if (memberInfo != null && memberInfo.Length > 0)
  {
    var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
    if (attrs != null && attrs.Length > 0)
      return ((DescriptionAttribute) attrs[0]).Description;
  }
  return str;
}

Then you can call it like this:

MyEnum.EnGb.GetDescription()

If it has a description attribute, you get that, if it doesn't, you get the .ToString() version, e.g. "EnGb". The reason I have something like this is to use an enum type directly on a Linq-to-SQL object, yet be able to show a pretty description in the UI. I'm not sure it fits your case, but throwing it out there as an option.

Nick Craver
Same idea and I was a minute faster, but your answer is more complete... ;-)
Lucero
@Lucero: Took a minute to crack open the project files ;)
Nick Craver
@Nick, I guessed so. Typing this error-free would have taken another minute or so, and since I didn't have a sample at hand, I just wrote down the "concept". Note that perfomance-wise one may want to add a dictionary which maps the enum values to their strings, so that's not really a problem.
Lucero
@Lucero - I agree, don't use this approach directly for performance...my use case it using this *maybe* a half dozen times per page load on the worst page and a low traffic site at that, if you're accessing it more often definitely put some cache layer for the result in there.
Nick Craver
thanks nick ;) its my answer
Sadegh
hm... now how i can cast enum by provided Description?
Sadegh
@Sadegh: You want to go from the description string back to the enum?
Nick Craver
@Nick yes exactly
Sadegh
@Sadegh: Have a look here: http://stackoverflow.com/questions/2787506 Just use a different attribute type, Description in this case, but it's the same approach.
Nick Craver
@Nick tanck's again man ;)
Sadegh
Probably you can combine Nick's and Matthew's answers to populate a `Dictionary<string,string>` once to decrease a number of refection calls.
abatishchev