2

I'm having an issue with formatting how I specifically want to display the enumeration items to the console window.

As of right now the Menu method displays the items in the enumeration as follow:

[1] CreateCustomer
[2] CreateAccount
[3] SetAccountBalance
[4] DisplayAccount Balance
[5] Exit

What I'm trying to accomplish well be to add the appropriate spaces between each menu option. For example, "CreateCustomer" to "Create Customer", "SetAccountBalance" to "Set Account Balance".

Menu Selection Enumeration

enum MenuSelection
{
   CreateCustomer = 1,
   CreateAccount = 2,
   SetAccountBalance = 3,
   DisplayAccountBalance = 4,
   Exit = 5,
   MaxMenuSelection = 5,
}

Display Menu Method

public static void Menu()
{
  for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
  {
     Console.WriteLine($"[{i}] {((MenuSelection)i).ToString()}");
  }
}

Any suggestions?

NTaveras
  • 73
  • 1
  • 8
  • Use the description attribute, See [here](https://stackoverflow.com/questions/2650080/how-to-get-c-sharp-enum-description-from-value) – maccettura Sep 28 '18 at 20:32

6 Answers6

3

I would use a Dictionary the key is MenuSelection and the value contain your customer display string.

Dictionary<MenuSelection, string> dict = new Dictionary<MenuSelection, string>();
dict.Add(MenuSelection.CreateCustomer, "Create Customer");
dict.Add(MenuSelection.CreateAccount, "Create Account");
dict.Add(MenuSelection.SetAccountBalance, "Set Account Balance");
dict.Add(MenuSelection.DisplayAccountBalance, "Display Account Balance");
dict.Add(MenuSelection.Exit, "Exit");

string showValue = string.Empty;
for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
{
    if (dict.TryGetValue((MenuSelection)i, out showValue))
    {
        Console.WriteLine($"[{i}] { showValue}");
    }           
}
D-Shih
  • 44,943
  • 6
  • 31
  • 51
1

One way is using the Display Attribute:

enum MenuSelection
{
   [Display(Name = "Create Customer")]
   CreateCustomer = 1,
   [Display(Name = "Create Account")]
   CreateAccount = 2,
   ...
}

But getting its value is not as easy as it should be. you can find it in How to get the Display Name Attribute of an Enum member via MVC razor code?

Another way that I use it myself is a function I have written that adds an space before each capital letter:

public static class Exts
{ 
    public static string CapitalSplit(this string x)
    {
         return Regex.Replace(x, "([a-z])([A-Z])", "$1 $2").Trim();
    }
}

Then you can use it like:

 for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
 {
     Console.WriteLine($"[{i}] {((MenuSelection)i).ToString().CapitalSplit()}");
 }
Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
0

You can use reflection to get the Description attribute (or Display attribute). Here I used an extension method to make it a little easier:

class Program
{
    static void Main(string[] args)
    {
        for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
        {
            Console.WriteLine($"[{i}] {((MenuSelection)i).GetEnumDescription()}");
        }

        Console.ReadLine();
    }
}

public static class Extensions
{
    public static string GetEnumDescription(this MenuSelection m)
    {
        FieldInfo fi = m.GetType().GetField(m.ToString());

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

        return attributes != null && attributes.Length > 0 ? attributes[0].Description : m.ToString();
    }
}

public enum MenuSelection
{
    [Description("Create Customer")]
    CreateCustomer = 1,
    [Description("Create Account")]
    CreateAccount = 2,
    [Description("Set Account Balance")]
    SetAccountBalance = 3,
    [Description("Display Account Balance")]
    DisplayAccountBalance = 4,
    Exit = 5,
    MaxMenuSelection = 5,
}

Result:

[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
Chris Dunaway
  • 10,974
  • 4
  • 36
  • 48
0

You can do like this

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    enum MenuSelection
    {
        CreateCustomer = 1,
        CreateAccount = 2,
        SetAccountBalance = 3,
        DisplayAccountBalance = 4,
        Exit = 5,
        MaxMenuSelection = 5,
    }

    public static void Main()
    {
        Enum
            .GetNames(typeof(MenuSelection))
            .Select(name => new 
            { 
                name, 
                index = (int)Enum.Parse(typeof(MenuSelection), name, true) 
            })
            .Select(kv => $"[{kv.index}] " + String.Join(" ", SplitByCamelCase(kv.name)))
            .Select(item => 
            {
                Console.WriteLine(item);
                return true;
            })
            .ToList();
    }

    public static bool IsLower(char ch) 
    {
        return ch >= 'a' && ch <= 'z';
    }

    public static string Head(string str)
    {
        return new String(
                    str
                        .Take(1)
                        .Concat(
                            str
                                .Skip(1)
                                .TakeWhile(IsLower)
                        )
                        .ToArray()
                );
    }

    public static string Tail(string str)
    {
        return new String(str.Skip(Head(str).Length).ToArray());
    }

    public static IEnumerable<string> SplitByCamelCase(string str) 
    {
        if (str.Length == 0) 
            return new List<string>();

        return 
            new List<string> 
            { 
                Head(str) 
            }
            .Concat(
                SplitByCamelCase(
                    Tail(str)
                )
            );
    }
}

Result:

[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection

See sample online

giokoguashvili
  • 2,013
  • 3
  • 18
  • 37
0

This is very quick and dirty. However, it has the advantage that you can create any menu with any enum type.

It separates words based on case (upper/lower) transitions. It works, except for your MaxMenuSelection. Instead of putting that in your enum, make it a template (on an enum type) function that return GetValues().Length (see below):

The where shown below is where T : struct because the compiler I'm using doesn't support where T : System.Enum which would be much better, but requires the latest compiler.

  public static string SeparateWords(string enumName)
  {
      var buffer = new StringBuilder();
      var wasLower = false;
      foreach (var c in enumName)
      {
          if (wasLower && char.IsUpper(c))
          {
              buffer.Append(' ');
          }

          buffer.Append(c);
          wasLower = char.IsLower(c);
      }

      return buffer.ToString();
  }

  public static void DisplayMenu<T>() where T : struct //should be System.Enum if possible
  {
      var enumType = typeof(T);
      var names = Enum.GetNames(enumType);
      var values = Enum.GetValues(enumType) as int[];
      for (var i = 0; i < names.Length; ++i)
      {
          Console.WriteLine($"[{values[i]}] {SeparateWords(names[i])}");
      }
  }

I get this output:

[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection

When I call this:

 EnumTest.DisplayMenu<MenuSelection>();

And, you can get the "Max Menu Selection" by doing this:

public static int MaxMenuSelection<T>() where T : struct
{
    return Enum.GetValues(typeof(T)).Length;
}
Flydog57
  • 6,851
  • 2
  • 17
  • 18
-1

Why not do something simple and add an _ in between the words?

Then you can do this:

    enum MenuSelection
    {
        Create_Customer = 1,
        Create_Account = 2,
        Set_Account_Balance = 3,
        Display_Account_Balance = 4,
        Exit = 5,
        MaxMenuSelection = 5,
    }
    public static void Menu()
    {
        for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
        {
            Console.WriteLine($"[{i}] {((MenuSelection)i).ToString().Replace("_"," ")}");
        }
    }

You get this as a result:

 [1] Create Customer
 [2] Create Account
 [3] Set Account Balance
 [4] Display Account Balance
 [5] Exit
Alexander Ryan Baggett
  • 2,347
  • 4
  • 34
  • 61