我有一个枚举,我想使用特殊方式将其表示为字符串:
public enum FailureDescription
{
MemoryFailure,
Fragmentation,
SegmentationFault
}
我想按如下方式打印该枚举的值:FailureDescription.MemoryFailure.ToString() - > Memory Failure
我可以那样做吗?怎么样?实现ToString?
您可以编写自己的扩展方法:
public static string ToFormattedText(this MyEnum value)
{
var stringVal = value.ToString();
var bld = new StringBuilder();
for (var i = 1; i < stringVal.Length; i++)
{
if (char.IsUpper(stringVal[i]))
{
bld.Append(" ");
}
bld.Append(stringVal[i]);
}
return bld.ToString();
}
如果希望所有枚举都可用的方法,只需将MyEnum
替换为Enum
。
用法:
var test = MyEnum.SampleName.ToFormattedText();
考虑缓存-每次构建字符串都不有效。
您还可以使用simple正则表达式和linq混合物提取和连接单词:
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));
其中:
([A-Z][a-z]+)(?=[A-Z]|$)
匹配以大写字母开头的单词,直到找到下一个大写字母或字符串结尾:DEMO at regex101
.Select(m => m.Groups[1].Value)
从组1中选择匹配的值
.Aggregate((str, next) => (str = str + " " + next));
连接单词并在单词之间插入空格。
使用Description属性装饰枚举值。我建议为资源添加resx
文件,以便您可以更轻松地进行本地化。如果您对“ Memory Failure”进行了硬编码,则可以将其更改为另一种语言(如注释中提到的Hans Passant)将变得更加艰巨。
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
}
然后您可以创建一个方法或扩展方法(如图所示)以读取Description
值。
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();
}
}
然后像这样调用方法
Console.WriteLine(FailureDescription.MemoryFailure.GetDescription());
这里是我一直在使用的实用程序之一。 @HansPassant在他的评论中提出了关于本地化的好观点。
此代码考虑了资源文件。在具有两个参数的属性中,第一个参数是“资源中的密钥”文件,其中,第二个参数是资源的命名空间。
签出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 ());
}
此扩展方法将为您完成:
public static string ToFormattedText(this FailureDescription value)
{
return new string(value.ToString()
.SelectMany(c =>
char.IsUpper(c)
? new [] { ' ', c }
: new [] { c })
.ToArray()).Trim();
}
遵循DRY和KISS原理的优雅解决方案是使用Humanizer:
"Memory Failure".DehumanizeTo<EnumUnderTest>(); // Returns FailureDescription.MemoryFailure.
"Fragmentation".DehumanizeTo<EnumUnderTest>(); // Returns FailureDescription.Fragmentation.
"Segmentation Fault".DehumanizeTo<EnumUnderTest>(); // Returns FailureDescription.SegmentationFault.