2

I have an enum which I want to present as string using special way:

public enum FailureDescription
{
   MemoryFailure,
   Fragmentation,
   SegmentationFault
}

I want to print the value of that enum as following : FailureDescription.MemoryFailure.ToString() - > Memory Failure Can I do that ? How? Implement ToString?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
YAKOVM
  • 9,805
  • 31
  • 116
  • 217

6 Answers6

3

You can write own extension method:

public static string ToFormattedText(this MyEnum value)
{
    var stringVal = value.ToString();   
    var bld = new StringBuilder();

    for (var i = 0; i < stringVal.Length; i++)
    {
        if (char.IsUpper(stringVal[i]))
        {
            bld.Append(" ");
        }

        bld.Append(stringVal[i]);
    }

    return bld.ToString();
}

If you want method available for all enums, just replace MyEnum with Enum.

Usage:

var test = MyEnum.SampleName.ToFormattedText();

Consider caching - building string everytime could not be efficient.

Steve Johnson
  • 3,054
  • 7
  • 46
  • 71
2

Use the Description attribute to decortate your enumeration values. I'd suggest adding a resx file for resources so that you can localise more easily. If you hardcoded "Memory Failure", it becomes more work to be able to change that to another language (as Hans Passant mentioned in the comments).

public enum FailureDescription
{
    [Description("Memory Failure")] //hardcoding English
    MemoryFailure,
    [Description(MyStringsResourceFile.FragmentationDescription)] //reading from a resx file makes localisation easier
    Fragmentation,
    [Description(MyStringsResourceFile.SegmentationFaultDescription)]
    SegmentationFault
}

You can then create a method, or extension method (as shown) to read the Description value.

public static class Extensions
{
    public static string GetDescription(this Enum value)
    {

        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes =
            (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute),
            false);

        if (attributes != null &&
            attributes.Length > 0)
            return attributes[0].Description;
        else
            return value.ToString();
    }
}

Then call the method like so

Console.WriteLine(FailureDescription.MemoryFailure.GetDescription());
keyboardP
  • 68,824
  • 13
  • 156
  • 205
1

This extension method will do it for you:

public static string ToFormattedText(this FailureDescription value)
{
    return new string(value.ToString()
        .SelectMany(c =>
            char.IsUpper(c)
            ? new [] { ' ', c }
            : new [] { c })
        .ToArray()).Trim();
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
0

You also can use a simple regex & linq mixture to extract and concatenate the words:

var withSpaces = 
    Regex
    .Matches(
        FailureDescription.MemoryFailureTest.ToString(), 
        @"([A-Z][a-z]+)(?=[A-Z]|$)")
    .Cast<Match>()
    .Select(m => m.Groups[1].Value)
    .Aggregate((str, next) => (str = str + " " + next));

DEMO at ideone.com

where:

([A-Z][a-z]+)(?=[A-Z]|$)

matches words that begin with upper-case letters until the next upper-case letter or the end of string is found: DEMO at regex101

.Select(m => m.Groups[1].Value)

selects the matched values from the group 1

.Aggregate((str, next) => (str = str + " " + next));

concatenates words and inserts a space between them.

t3chb0t
  • 16,340
  • 13
  • 78
  • 118
0

Here is one of the utilities I've been using. @HansPassant in his comment raised a good point about localizing.

This code takes Resource files into consideration. In the attribute with two params first param is the Key in Resource file, where as the second param is the namespace for the resource.

Checkout the git repo https://github.com/seanpaul/EnumExtensions

public enum TestEnum
{
    //You can pass what ever string value you want
    [StringValue("From Attribute")]
    FromAttribute = 1,

    //If localizing, you can use resource files
    //First param is Key in resource file, second is namespace for Resources.
    [StringValue("Test", "EnumExtensions.Tests.Resources")]
    FromResource = 2,

    //or don't mention anything and it will use built-in ToString
    BuiltInToString = 3
}

[Test ()]
public void GetValueFromAttribute ()
{
    var testEnum = TestEnum.FromAttribute;
    Assert.AreEqual ("From Attribute", testEnum.GetStringValue ());
}
[Test ()]
public void GetValueFromResourceFile ()
{
    var testEnum = TestEnum.FromResource;
    Assert.AreEqual ("From Resource File", testEnum.GetStringValue ());
}
Sai Puli
  • 951
  • 8
  • 12
0

An elegant solution following the DRY and KISS principles would be using Humanizer:

"Memory Failure".DehumanizeTo<EnumUnderTest>(); // Returns FailureDescription.MemoryFailure.
"Fragmentation".DehumanizeTo<EnumUnderTest>(); // Returns FailureDescription.Fragmentation.
"Segmentation Fault".DehumanizeTo<EnumUnderTest>(); // Returns FailureDescription.SegmentationFault.
Lesair Valmont
  • 796
  • 1
  • 8
  • 15