tags:

views:

334

answers:

11

I want to have an enum as in:

enum FilterType
{
   Rigid = "Rigid",
   SoftGlow = "Soft / Glow",
   Ghost = "Ghost",
}

How to achieve this? Is there a better way to do this? It's gonna be used for an instance of an object where it's gonna be serialized/deserialized. It's also gonna populate a dropdownlist.

+1  A: 

This is not possible. C# only allows integral enum types (int, short, long, etc.). You can either create a lightweight "enum-like" class or use static constants.

static class FilterTypes
{
    public const string Rigid = "Rigid";
    // ...
}

// or ...

class FilterType
{
    static readonly FilterType RigidFilterType = new FilterType("Rigid");

    string name;

    FilterType(string name)  // private constructor
    {
        this.name = name;
    }

    public static FilterType Rigid
    {
        get { return FilterType.RigidFilterType; }
    }

    // ...
}
bobbymcr
+1 for imlementing a class or struct to behave this way.
csharptest.net
A: 

No, it's not possible.

The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.

However, you can retrieve the declared name of an enum with the Enum class:

string name = Enum.GetName(typeof(FilterType), FilterType.Rigid);

If this doesn't work for you, a collection of string constants collected in a class might.

Michael Petrotta
+1  A: 

Enums are always linked to an integer value. So no. You can do FilterType.Rigid.ToString() to obtain the string value although it can't be localized directly.

Etienne Brouillard
+8  A: 

No, but if you want to scope "const" strings and use them like an enum, here's what I do:

public static class FilterType
{
   public const string Rigid = "Rigid";
   public const string SoftGlow =  "Soft / Glow";
   public const string Ghost ="Ghost";
}
Dave Markle
This is how I've done this in the past as well, works well for most purposes.
Seth
The downside to this approach is that I can't see how you could automatically populate a drop down. With a little work you at least have the option of iterating the values of an enum.
Michael Gattuso
@Michael: you probably could iterate with some (messy) reflection code.
Dan
Or you could define a static string Values[] array.
Dave Markle
DV for NO in ..."No, but if you want to scope "const" strings ..."
Shankar Ramachandran
+1  A: 

You can get the Enum name as a string like this

FilterType myType = FilterType.Rigid;
String strType = myType.ToString();

However, you may be stuck with the Camel Case/Hungarian notation, but you can easily convert that to a more user friendly String using a method like this (Not the prettiest solution, I would be grateful for input on optimizing this):

Public Shared Function NormalizeCamelCase(ByVal str As String) As String

    If String.IsNullOrEmpty(str) Then
        Return String.Empty
    End If

    Dim i As Integer = 0
    Dim upperCount As Integer = 0
    Dim otherCount As Integer = 0
    Dim normalizedString As String = str

    While i < normalizedString.Length

        If Char.IsUpper(normalizedString, i) Then
            ''Current char is Upper Case
            upperCount += 1
            If i > 0 AndAlso Not normalizedString(i - 1).Equals(" "c) Then
                ''Current char is not first and preceding char is not a space
                ''...insert a space, move to next char
                normalizedString = normalizedString.Insert(i, " ")
                i += 1
            End If
        ElseIf Not Char.IsLetter(normalizedString, i) Then
            otherCount += 1
        End If

        ''Move to next char
        i += 1

    End While

    If upperCount + otherCount = str.Length Then
        ''String is in all caps, return original string 
        Return str
    Else
        Return normalizedString
    End If

End Function

If that's still not pretty enough, you may want to look into Custom Attributes, which can be retrieved using Reflection...

Joey
+9  A: 
using System.ComponentModel;   
enum FilterType
{
    [Description("Rigid")]
    Rigid,
    [Description("Soft / Glow")]
    SoftGlow,
    [Description("Ghost")]
    Ghost ,
}

You can get the value out like this

public static String GetEnumerationDescription(Enum e)
{
  Type type = e.GetType();
  FieldInfo fieldInfo = type.GetField(e.ToString());
  DescriptionAttribute[] da = (DescriptionAttribute[])(fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false));
  if (da.Length > 0)
  {
    return da[0].Description;
  }
  return e.ToString();
}
Shaun Bowe
Nice approach. You could even have this as an extension method for all enums.
0xA3
Thanks.. I have quite a few static methods that I use on my current project to deal with enums like this. I never thought of using an extension method though. Ill have to give that a try
Shaun Bowe
It is a good practice to serialize this by...defining one more attribute....on [System.Xml.Serialization.XmlEnum("Rigid")] ...[Description("Rigid")]Rigid,...etc.
Shankar Ramachandran
+1  A: 

No, but you can cheat like this:

public enum FilterType{
   Rigid,
   SoftGlow,
   Ghost
}

And then when you need their string values you can just do FilterType.Rigid.ToString()

Malfist
Doing it this way (which I'm guilty of too) shows the user text without spaces/special characters (SoftGlow as opposed to "Soft / Glow"), which I'm sure he wants to be able to do.
Pwninstein
A: 

You can use an Attribute over the values

[System.ComponentModel.Description("Rigid")]

example:

 enum FilterType
{
   [System.ComponentModel.Description("Rigid")]
   Rigid,
    [System.ComponentModel.Description("Soft / Glow")]
   SoftGlow,
    [System.ComponentModel.Description("Ghost")]
   Ghost
}

and use Reflection to get the descriptions.

Enum extension method:

public static string GetDescription(this Enum en)
    {
        var type = en.GetType();
        var memInfo = type.GetMember(en.ToString());

        if (memInfo != null && memInfo.Length > 0)
        {
            var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (attrs != null && attrs.Length > 0)
                return ((DescriptionAttribute)attrs[0]).Description;
        }
        return en.ToString();
    }

use it:

FilterType = FilterType.Rigid;
            string description= result.GetDescription();
CSharpAtl
+1  A: 

In the System.ComponentModel namespace there is a class DescriptionAttribute that works well here.

enum FilterType
{
   Rigid,
   [Description("Soft / Glow")]
   SoftGlow,
   Ghost,
}

Then to get the description and fail over to the ToString()

var descriptionAttribute = Value.GetType()
 .GetField(Value.ToString())
 .GetCustomAttributes(typeof(DescriptionAttribute), false)
 .OfType <DescriptionAttribute>()
 .FirstOrDefault()??new DescriptionAttribute(Value.ToString());
Josh Bush
+1  A: 

If you're comfortable with extension methods, you can easily do what you're after:

//Can return string constants, the results of a Database call, 
//or anything else you need to do to get the correct value 
//(for localization, for example)
public static string EnumValue(this MyEnum e) {
    switch (e) {
        case MyEnum.First:
            return "First Friendly Value";
        case MyEnum.Second:
            return "Second Friendly Value";
        case MyEnum.Third:
            return "Third Friendly Value";
    }
    return "Horrible Failure!!";
}

This way you can do:

Private MyEnum value = MyEnum.First;
Console.WriteLine(value.EnumValue());
Pwninstein
A: 

Along the lines of Shaun Bowe's example you can also do this in C# 3 with an extension method for enum (I did not come up with and cannot, for the life of me, remember where I did).

Create an Attribute:

public class DisplayTextAttribute : Attribute {
  public DisplayTextAttribute(String text) {
  Text = text;
  }
  public string Text { get; set; }
}

Create an extension:

public static class EnumHelpers {
  public static string GetDisplayText(this Enum enumValue) {
    var type = enumValue.GetType();
    MemberInfo[] memberInfo = type.GetMember(enumValue.ToString());

    if (memberInfo == null || memberInfo.Length == 0)
      return enumValue.ToString();

    object[] attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayTextAttribute), false);
    if (attributes == null || attributes.Length == 0)
      return enumValue.ToString();

    return ((DisplayTextAttribute)attributes[0]).Text;
  }
}

I've found this to be really tidy solution. In your enum add the following:

enum FilterType{
  Rigid,
  [DisplayText("Soft / Glow")]
  SoftGlow,
  Ghost
}

You could then access FilterType.GetDisplayText() which will pull back the string for the unattributed enums and the displayText for the ones with attributes.

Michael Gattuso
Interesting approach. Just make sure you don't use this code in a "high performance" path, since it's quite expensive to do reflection calls.
bobbymcr