我有这样的枚举:
public enum ObectTypes
{
TypeOne,
TypeTwo,
TypeThree,
...
TypeTwenty
}
然后我需要将这个枚举转换为字符串。现在我就是这样做的:
public string ConvertToCustomTypeName(ObjectTypes typeObj)
{
string result = string.Empty;
switch (typeObj)
{
case ObjectTypes.TypeOne: result = "This is type T123"; break;
case ObjectTypes.TypeTwo: result = "Oh man! This is type T234"; break;
...
case ObjectTypes.TypeTwenty: result = "This is type last"; break;
}
return result;
}
我很确定有更好的方法来做到这一点,我正在寻找一些好的实践解决方案。
编辑:结果字符串中没有一种模式。
提前致谢。
我使用
[Description]
中的
System.ComponentModel
属性
示例:
public enum RoleType
{
[Description("Allows access to public information")] Guest = 0,
[Description("Allows access to the blog")] BlogReader = 4,
}
然后我就读它
public static string ReadDescription<T>(T enumMember)
{
var type = typeof (T);
var fi = type.GetField(enumMember.ToString());
var attributes = (DescriptionAttribute[])
fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
return attributes.Length > 0 ?
attributes[0].Description :
enumMember.ToString();
}
然后使用
ReadDescription(RoleType.Guest);
注意:此解决方案假设单一文化应用程序,因为没有专门询问多种文化。如果您需要处理多种文化,我会使用
DescriptionAttribute
或类似工具来存储文化感知资源文件的密钥。虽然您可以将枚举成员直接存储在 .resx 文件中,这将创建尽可能紧密的耦合。我认为您没有理由希望将应用程序的内部工作(枚举成员名称)与出于国际化目的而存在的键值结合起来。
如果您需要自定义字符串,最好的选择是创建
Dictionary< ObjectTypes, string>
,然后进行字典查找。
如果您对默认的 ToString() 功能感到满意,只需使用
typeObj.ToString();
对于字典方法,你可以这样做:
private static Dictionary<ObjectTypes, string> enumLookup;
static MyClass()
{
enumLookup = new Dictionary<ObjectTypes, string>();
enumLookup.Add(ObjectTypes.TypeOne, "This is type T123");
enumLookup.Add(ObjectTypes.TypeTwo, "This is type T234");
// enumLookup.Add...
}
你的方法变成:
public string ConvertToCustomTypeName(ObjectTypes typeObj)
{
// Shouldn't need TryGetValue, unless you're expecting people to mess with your enum values...
return enumLookup[typeObj];
}
使用建议的资源方式:
string GetName(Enum e) {
return Properties.Resources.ResourcesManager.GetString("_enum_"+e.GetType().ToString().Replace('.','_'));
}
错误处理有点多..
我认为最简单的方法是拥有一个在枚举值和首选短名称之间映射的函数,然后创建另一个生成完整消息的函数。
internal static string MapToName(ObjectTypes value) {
switch (value) {
case ObjectTypes.TypeOne: return "T123";
case ObjectTypes.TypeTwo: return "T234";
...
}
}
public string ConvertToCustomTypeName(ObjectTypes value) {
return String.Format("This is type {0}", MapToName(value));
}
我曾经在枚举字段上使用了一个自定义属性,该属性采用字符串参数,然后编写了一个函数来在给定枚举值时提取字符串。
如果您只想使用枚举的名称(即 TypeOne ),您可以简单地对枚举本身调用 ToString()
typeObj.ToString()
如果您想要基于类型的自定义字符串,您有多种不同的选择。您拥有的 switch 语句没问题,但如果您有大量枚举,维护它会变得混乱。或者您可以使用枚举类型作为键、字符串作为值来设置字典。
public enum ObectTypes
{
One,
Two
}
Dictionary<ObectTypes, String> myDic = new Dictionary<ObectTypes, string>();
myDic.Add( ObectTypes.One, "Something here for One" );
myDic.Add( ObectTypes.Two, "Something here for Two" );
我不太相信这一点...为什么没有人建议资源文件?
将枚举值映射到编译代码中的字符串作为一种快速破解方法是很好的,但从长远来看,这是一种不好的做法,并且使得重构代码变得困难。如果从枚举中添加(或减去)一个值会怎样?如果您使用资源文件中的字符串,您所要做的就是添加(或删除)一个条目。
我会将这些值放入数据库中。角色通常属于数据库有几个原因,包括:
如果操作正确,从数据库获取角色的性能不应该成为问题。此外,由于角色定义表很少更改,因此它非常适合缓存。
如果您发现自己必须破解 Enum 才能使其正常工作,也许您不应该使用 Enum。如果放置得当,一切都应该在代码中流畅得多,几乎不需要任何修改。授予枚举有其一席之地;例如,相当静态的互斥状态。
我想说,这需要重构。
您已经使用的模式并不是一个坏模式。几乎所有其他选择都有其自身的问题。如果您使用 F# 来处理这种类型,您可以执行以下操作:
type ObjectTypes =
| TypeOne
| TypeTwo
| TypeThree
...
| TypeTwenty
with override this.ToString() =
match this with
| TypeOne -> "This is type T123"
| TypeTwo -> "Oh man! This is type T234"
...
| TypeTwenty -> "This is type last"
| _ -> "This is any other type that wasn't explicitly specified"
当然,使用 F# 模式匹配,您比使用简单的 C# switch 语句拥有更多的控制权。
.NET 8 极大地提高了枚举性能。请参阅https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#enums
还对 Enum 进行了其他改进。 dotnet/运行时#76162 提高了 ToString 等各种方法的性能 IsDefined 在所有枚举的定义值都是的情况下 从 0 开始连续。在这种常见情况下,内部函数 查找 EnumInfo 中的值可以这样做 使用简单的数组访问,而不需要搜索 目标。