Hello,
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?
Hello,
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?
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 As Henk points out, this won't work for \uxxxxV
were xxxx
is the hexadecimal number representing the Unicode code point for %
. This is far from recommended.%
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.
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
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
}
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
As a reminder
I hope I can help someone.
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
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 = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : enumMember.ToString();
}
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.