更改枚举菜单名称格式 [C#]
Alter Enumeration Menu Name Format [C#]
我在格式化我特别希望将枚举项显示到控制台的方式时遇到问题 window。
截至目前,Menu 方法显示枚举中的项目如下:
[1] CreateCustomer
[2] CreateAccount
[3] SetAccountBalance
[4] DisplayAccount Balance
[5] Exit
我想要完成的是在每个菜单选项之间添加适当的空格。例如,
"CreateCustomer" 到 "Create Customer"、"SetAccountBalance" 到 "Set Account Balance"。
菜单选择枚举
enum MenuSelection
{
CreateCustomer = 1,
CreateAccount = 2,
SetAccountBalance = 3,
DisplayAccountBalance = 4,
Exit = 5,
MaxMenuSelection = 5,
}
显示菜单方法
public static void Menu()
{
for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
{
Console.WriteLine($"[{i}] {((MenuSelection)i).ToString()}");
}
}
有什么建议吗?
我会使用 Dictionary
,key
是 MenuSelection
,value
包含您的客户显示字符串。
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}");
}
}
一种方法是使用显示属性:
enum MenuSelection
{
[Display(Name = "Create Customer")]
CreateCustomer = 1,
[Display(Name = "Create Account")]
CreateAccount = 2,
...
}
但获得它的价值并不像它应该的那么容易。你可以在 How to get the Display Name Attribute of an Enum member via MVC razor code?
中找到它
我自己使用的另一种方法是我编写的一个函数,它在每个大写字母前添加一个 space:
public static class Exts
{
public static string CapitalSplit(this string x)
{
return Regex.Replace(x, "([a-z])([A-Z])", " ").Trim();
}
}
然后你可以像这样使用它:
for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
{
Console.WriteLine($"[{i}] {((MenuSelection)i).ToString().CapitalSplit()}");
}
您可以使用反射来获取Description 属性(或Display 属性)。这里我用了一个扩展的方法,让它更简单一些:
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,
}
结果:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
你可以这样做
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)
)
);
}
}
结果:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection
为什么不做点简单的,在单词之间加一个_?
那么你可以这样做:
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("_"," ")}");
}
}
结果是:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
这是非常快速和肮脏的。但是,它的优点是您可以使用任何 enum
类型创建任何菜单。
它根据大小写 (upper/lower) 转换来分隔单词。它有效,除了你的 MaxMenuSelection。不要把它放在你的枚举中,而是让它成为一个模板(在枚举类型上)函数 return GetValues().Length(见下文):
下面显示的where
是where T : struct
,因为我使用的编译器不支持where T : System.Enum
这样会好很多,但需要最新的编译器。
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])}");
}
}
我得到这个输出:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection
当我调用这个时:
EnumTest.DisplayMenu<MenuSelection>();
而且,您可以通过这样做获得 "Max Menu Selection":
public static int MaxMenuSelection<T>() where T : struct
{
return Enum.GetValues(typeof(T)).Length;
}
我在格式化我特别希望将枚举项显示到控制台的方式时遇到问题 window。
截至目前,Menu 方法显示枚举中的项目如下:
[1] CreateCustomer
[2] CreateAccount
[3] SetAccountBalance
[4] DisplayAccount Balance
[5] Exit
我想要完成的是在每个菜单选项之间添加适当的空格。例如, "CreateCustomer" 到 "Create Customer"、"SetAccountBalance" 到 "Set Account Balance"。
菜单选择枚举
enum MenuSelection
{
CreateCustomer = 1,
CreateAccount = 2,
SetAccountBalance = 3,
DisplayAccountBalance = 4,
Exit = 5,
MaxMenuSelection = 5,
}
显示菜单方法
public static void Menu()
{
for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
{
Console.WriteLine($"[{i}] {((MenuSelection)i).ToString()}");
}
}
有什么建议吗?
我会使用 Dictionary
,key
是 MenuSelection
,value
包含您的客户显示字符串。
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}");
}
}
一种方法是使用显示属性:
enum MenuSelection
{
[Display(Name = "Create Customer")]
CreateCustomer = 1,
[Display(Name = "Create Account")]
CreateAccount = 2,
...
}
但获得它的价值并不像它应该的那么容易。你可以在 How to get the Display Name Attribute of an Enum member via MVC razor code?
中找到它我自己使用的另一种方法是我编写的一个函数,它在每个大写字母前添加一个 space:
public static class Exts
{
public static string CapitalSplit(this string x)
{
return Regex.Replace(x, "([a-z])([A-Z])", " ").Trim();
}
}
然后你可以像这样使用它:
for (int i = 1; i <= (int)MenuSelection.MaxMenuSelection; i++)
{
Console.WriteLine($"[{i}] {((MenuSelection)i).ToString().CapitalSplit()}");
}
您可以使用反射来获取Description 属性(或Display 属性)。这里我用了一个扩展的方法,让它更简单一些:
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,
}
结果:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
你可以这样做
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)
)
);
}
}
结果:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection
为什么不做点简单的,在单词之间加一个_?
那么你可以这样做:
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("_"," ")}");
}
}
结果是:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
这是非常快速和肮脏的。但是,它的优点是您可以使用任何 enum
类型创建任何菜单。
它根据大小写 (upper/lower) 转换来分隔单词。它有效,除了你的 MaxMenuSelection。不要把它放在你的枚举中,而是让它成为一个模板(在枚举类型上)函数 return GetValues().Length(见下文):
下面显示的where
是where T : struct
,因为我使用的编译器不支持where T : System.Enum
这样会好很多,但需要最新的编译器。
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])}");
}
}
我得到这个输出:
[1] Create Customer
[2] Create Account
[3] Set Account Balance
[4] Display Account Balance
[5] Exit
[5] Max Menu Selection
当我调用这个时:
EnumTest.DisplayMenu<MenuSelection>();
而且,您可以通过这样做获得 "Max Menu Selection":
public static int MaxMenuSelection<T>() where T : struct
{
return Enum.GetValues(typeof(T)).Length;
}