19

For example:

public enum Unit{ KW, kV, V, Hz, %V } 

In this case % is a special character. So, how can I put this char in a enum?

3
  • 7
    Short and Long answer: You can't... Commented Mar 3, 2010 at 18:42
  • I'm not sure why you are after special characters in your enum, however if you are like me and you need to display a better name than perhaps type using the XmlEnumAttribute values for an Enum Check out my blog for more details http://www.bryanavery.co.uk/post/2010/01/08/How-do-you-retrieving-the-XmlEnumAttribute-values-for-an-Enum.aspx Commented Mar 3, 2010 at 18:46
  • 1
    Even if you can (based on a possible answer below), it is really, really bad practice, because every time you try to use it, it's going to muddy up the code readability. Commented Mar 3, 2010 at 18:48

7 Answers 7

36

Even if you could do that (and it looks you can't), it probably wouldn't be a good idea, because you'd be mixing how the enum should be displayed with the program code to manipulate it. A better option would be to define an attribute (or use existing DisplayNameAttribute) and annotate your enum with names as additional meta-data:

public enum Unit{ [DisplayName("Hz")] Hertz, [DisplayName("%V")] Volt } 
Sign up to request clarification or add additional context in comments.

2 Comments

+1 on this approach. We use a DisplayKeyAttribute which correlates an enum value with a localizable string.
I used the Description attribute instead since I received this error when using DisplayName: "Attribute 'DisplayName' is not valid on this declaration type. It is only valid on 'class, method, property, indexer, event' declarations."
12

Enum members shouldn't be used for user interface display purposes. They should be mapped to a string in order to get displayed. You can create a string array (or a dictionary) that maps each enum member to a string for user interaction.

That said, to answer your question directly, you can use \uxxxxV were xxxx is the hexadecimal number representing the Unicode code point for %. This is far from recommended. As Henk points out, this won't work for % as it's not in Unicode classes Lu, Ll, Lt, Lm, Lo, Nl, Mn, Mc, Nd, Pc, Cf (letters, digits, connecting, and formatting characters). Only these characters are acceptable for identifiers.

8 Comments

if \\xxx is not accepted as an alpha char (and % isn't) this still gives a compile error. % = \0025
Content where content belongs. Better to associate the strings with the enum members using an attibute then using a separate string array.
@AMissico: It's not always practical to do that. For example, when you have [Flags] enums, there won't be one to one relationship between values of an enum types to enum members.
@Mehrdad, true, but usually flag enums are not represented to the user as strings.
@AMissico: I can see of some cases where they are. Anyway, another reason I prefer an imperative mapping (rather than a declarative one, which is useful in plenty of cases) is that going back from the string representation to the enum value is much easier.
|
7

Just to register another way to do that, in a simple way, you can define "your own" enumerator with constants. In your example

public class UnitEnum { public const string KW = "KW"; public const string Volt = "%V"; } 

To access, it just: UnitEnum.Volt

Comments

4

This answer is related to the one from @Coppermill I feel using the DescriptionAttribute is more semantically correct when working with Enums

public enum ReportStatus { [Description("Reports that are running")] Running, [Description("Reports that are pending to run")] Pending, [Description("Reports that have errored while running")] Error, [Description("Report completed successfully.")] Finished } 

Then I read from it like such

 public static bool IsNullable(this Type type) { if (!type.IsGenericType) return false; var g = type.GetGenericTypeDefinition(); return (g.Equals(typeof (Nullable<>))); } public static Type ConcreteType(this Type type) { if (IsNullable(type)) type = UnderlyingTypeOf(type); return type; } 

.

 public static string ReadDescription<T>(T enumMember) { if (typeof (T).IsNullable() && enumMember == null) return null; var type = (typeof (T).ConcreteType()); var fi = type.GetField(enumMember.ToString()); var attributes = fi.GetCustomAttributes(typeof (DescriptionAttribute), false); if(attributes.Length == 0) return enumMember.ToString(); return attributes.Cast<DescriptionAttribute>().First().Description; } 

Then usage would be ReadDescription(ReportStatus.Running) I also have a method that will convert an Enum into a KeyValuePair Enumerable for binding an Enum to a DropDown.

1 Comment

As a follow up to this many years later. I've stopped using enums unless i actually intended to use [Flags]. At this point I use static classes and strong types instead. See stackoverflow.com/q/19324419/37055
0

Sorry, but I just realized that I didn't answer the question. I will not delete my answer because someone may find these code snippets helpful.


I agree completely with Tomas Petricek, so I will not repeat his answer.

Here is my solution to the problem. I been using this code for about five years. I decided to create a custom attribute in order to use the DisplayName attribute for captions and such.


Public Module MainModule Public Sub Main() Console.WriteLine(EnumEx.GetNumberFormatString(Unit.Volt), 120.13) End Sub End Module 

Public Enum Unit <NumberFormatString("{0} Hz"), DisplayName("Hertz")> Hz <NumberFormatString("{0} %V"), DisplayName("%Volt")> pV End Enum 

<AttributeUsage(AttributeTargets.All)> _ Public NotInheritable Class NumberFormatStringAttribute Inherits Attribute Public Shared ReadOnly [Default] As NumberFormatStringAttribute = New NumberFormatStringAttribute Private _format As String Public Sub New() Me.New(Char.MinValue) End Sub Public Sub New(ByVal format As String) _format = format End Sub Public Overrides Function Equals(ByVal obj As Object) As Boolean If (obj Is Me) Then Return True End If Dim oAttribute As NumberFormatStringAttribute = TryCast(obj, NumberFormatStringAttribute) If (Not oAttribute Is Nothing) Then Return (oAttribute.NumberFormatString = Me.NumberFormatString) End If Return False End Function Public Overrides Function GetHashCode() As Integer Return Me.NumberFormatString.GetHashCode End Function Public Overrides Function IsDefaultAttribute() As Boolean Return Me.Equals(NumberFormatStringAttribute.Default) End Function Public ReadOnly Property NumberFormatString() As String Get Return Me.NumberFormatStringValue End Get End Property Private Property NumberFormatStringValue() As String Get Return _format End Get Set(ByVal value As String) _format = value End Set End Property End Class 

Public NotInheritable Class EnumEx Private Sub New() End Sub Public Shared Function GetNumberFormatString(ByVal value As Object) As String Dim sResult As String = Nothing Dim oFieldInfo As System.Reflection.FieldInfo = value.GetType.GetField(value.ToString) If Not (oFieldInfo Is Nothing) Then Dim oCustomAttributes() As Object = oFieldInfo.GetCustomAttributes(GetType(NumberFormatStringAttribute), True) If (Not (oCustomAttributes Is Nothing)) AndAlso oCustomAttributes.Length > 0 Then sResult = DirectCast(oCustomAttributes(0), NumberFormatStringAttribute).NumberFormatString End If End If Return sResult End Function End Class 

Comments

0

Enum members shouldn't be used for user interface display purposes. But you can use simple tricks with DisplayName("Your Property Display Name") for this matter as bellow.

//Enum public enum ErrorCodes { [DisplayName("U-volt")] UVolt = 2, [DisplayName("L-trip")] Ltrip = 5 } //Here you can retrive Display name as bellow public class MyClass{ public void readEnumDisplayName(){ String ErroCode = Enum.GetName(typeof(ErrorCodes), 5); // Find Error Name using Integer value MemberInfo property = typeof(ErrorCodes).GetRuntimeField(ErroCode); //Find Field var dd = property.GetCustomAttribute(typeof(DisplayNameAttribute)) as DisplayNameAttribute; //Find Display Attribute if (dd != null) //Check if null { var name = dd.DisplayName; //Retrive Display name } } } 

Comments

-2

Some can state that Enumerations are for Code only, I must disagree and I use to Code and Display functionality.

In your particular case I would use the full word

public enum UnitType { Kilowatt, Kilovolt, Volt, Hertz, Ohm, Faraday } 

So I can use them in a Dropdown for example as (when I need to create a new item, all I need to do is append that item into the Enumeration...

ddl.Items.Clear(); foreach (string type in Enum.GetNames(typeof(UnitType))) ddl.Items.Add(type); 

I tend to use Space Separator, but I normally use underscore to make spaces, like

public enum myType { Process_Time, Process_Order, Process_Invoices } 

and the DropDownList item would be

ddl.Items.Add(type.Replace("_", " ")); 

when I want to set the Type from the DropDown, I use the Parse

UnitType unit = (UnitType)Enum.Parse( typeof(UnitType), ddl.SelectedValue.toString()); 

off course, if you use Separator

 ddl.SelectedValue.toString().Replace(" ", "_")); 

Some rules to have in consideration to write better code

  • Always write Type to an Enum, in you case Unit should be UnitType
  • Use Title Case for Enumeration Objects

As a reminder

  • You can use an Enum in a Bit Operation adding [Flags] keyword
  • You can specify the integer value of the Enum if you don't want to have: 0, 1, 2, 3...

I hope I can help someone.

2 Comments

Down voted because you are hard-coding your actual code for presentation purposes.
You should bin any refactoring book that recommends you do this. Your code is brittle and hard to refactor because changing the enum causes your UI to break - and I doubt you have integration tests at that level so it'll probably go live.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.