Enum Tostring With User Friendly Strings

Enum ToString with user friendly strings

I use the Description attribute from the System.ComponentModel namespace. Simply decorate the enum:

private enum PublishStatusValue
{
[Description("Not Completed")]
NotCompleted,
Completed,
Error
};

Then use this code to retrieve it:

public static string GetDescription<T>(this T enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}

//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}

Associating enums with strings in C#

I like to use properties in a class instead of methods, since they look more enum-like.

Here's an example for a Logger:

public class LogCategory
{
private LogCategory(string value) { Value = value; }

public string Value { get; private set; }

public static LogCategory Trace { get { return new LogCategory("Trace"); } }
public static LogCategory Debug { get { return new LogCategory("Debug"); } }
public static LogCategory Info { get { return new LogCategory("Info"); } }
public static LogCategory Warning { get { return new LogCategory("Warning"); } }
public static LogCategory Error { get { return new LogCategory("Error"); } }
}

Pass in type-safe string values as a parameter:

public static void Write(string message, LogCategory logCategory)
{
var log = new LogEntry { Message = message };
Logger.Write(log, logCategory.Value);
}

Usage:

Logger.Write("This is almost like an enum.", LogCategory.Info);

Friendly Enum Strings With Flags Attribute

You can write a method just as in the answer you link, but with support for flag enums, and return a comma seperated string, something like:

public static string GetDescription(Enum value)
{
Type type = value.GetType();
var values = Enum.GetValues(type);
var setValues = new List<Enum>();
foreach(var enumValue in values)
{
if (value.HasFlag((Enum)enumValue))
setValues.Add((Enum)enumValue);
}
var stringList = new List<string>();
foreach (var singleValue in setValues)
{
var name = Enum.GetName(type, singleValue);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr =
Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
stringList.Add(attr.Description);
}
}
}
}
return string.Join(",", stringList.ToArray());
}

not the cleanest code, but you get the idea, only keep in my mind, that it wont work as expected for enums that are not flags - just throwing an idea.

Using Enum values as String literals

You can't. I think you have FOUR options here. All four offer a solution but with a slightly different approach...

Option One: use the built-in name() on an enum. This is perfectly fine if you don't need any special naming format.

    String name = Modes.mode1.name(); // Returns the name of this enum constant, exactly as declared in its enum declaration.

Option Two: add overriding properties to your enums if you want more control

public enum Modes {
mode1 ("Fancy Mode 1"),
mode2 ("Fancy Mode 2"),
mode3 ("Fancy Mode 3");

private final String name;

private Modes(String s) {
name = s;
}

public boolean equalsName(String otherName) {
// (otherName == null) check is not needed because name.equals(null) returns false
return name.equals(otherName);
}

public String toString() {
return this.name;
}
}

Option Three: use static finals instead of enums:

public final class Modes {

public static final String MODE_1 = "Fancy Mode 1";
public static final String MODE_2 = "Fancy Mode 2";
public static final String MODE_3 = "Fancy Mode 3";

private Modes() { }
}

Option Four: interfaces have every field public, static and final:

public interface Modes {

String MODE_1 = "Fancy Mode 1";
String MODE_2 = "Fancy Mode 2";
String MODE_3 = "Fancy Mode 3";
}


Related Topics



Leave a reply



Submit