C# 更优雅的enum设计
我在为C#学习 我听说C#是最具可构造性的语言之一。你们能让我的代码更加优雅高效吗C# 更优雅的enum设计,c#,enums,C#,Enums,我在为C#学习 我听说C#是最具可构造性的语言之一。你们能让我的代码更加优雅高效吗 public class ISO639 { public enum ISO639Code { Afrikaans, //af Albanian, //sq Amharic, //am ...
public class ISO639
{
public enum ISO639Code
{
Afrikaans, //af
Albanian, //sq
Amharic, //am
...
Yiddish, //yi
Unknown
}
public static string GetISO639CodeString(ISO639.ISO639Code l)
{
switch (l)
{
case ISO639Code.English: return "en";
case ISO639Code.Japanese: return "ja";
...
case ISO639Code.Hebrew: return "he";
default: return "";
}
public static ISO639.ISO639Code GetISO39CodeValue(string s)
{
switch (s)
{
case "ko" : return ISO639Code.Korean;
case "en" : return ISO639Code.English;
...
case "hu" : return ISO639Code.Hungarian;
default: return ISO639Code.Unknown;
}
}
}
这是我的班级ISO639。这个类为ISO639代码提供枚举,但我需要从ISO639枚举到普通字符串的类型转换。(例如ISO639.ISO639Code.Italian=>“it”)。我还需要从普通字符串到ISO639枚举的类型转换。(例如,“it”=>ISO639.ISO639Code.意大利语)
有更有效的编码方式吗?当然。您可以使用:
我建议您对枚举使用C#扩展方法,它们允许您添加任何需要的逻辑
例如,请参见我只需将信息存储在类似字典的对象中。通过这种方式,您可以按键引用名称并直接获取值。使用字典,例如:
新建字典
您可以将标准属性添加到每个枚举条目中,然后读取它
公共枚举ISO639Code
{
[说明(“af”)]
南非荷兰语
}
公共静态类枚举扩展
{
//用于读取描述值的扩展方法
公共静态字符串GetDescription(此枚举currentEnum)
{
var fi=currentEnum.GetType().GetField(currentEnum.ToString());
var da=(DescriptionAttribute)Attribute.GetCustomAttribute(fi,typeof(DescriptionAttribute));
返回da!=null?da.Description:currentEnum.ToString();
}
}
//**如何阅读**
ISO639Code等代码=ISO639Code.南非荷兰语;
//这将返回“af”
字符串isoDescription=isoCode.GetDescription();
编辑:
string searchFor = "af";
ISO639Code foundEntry;
// Loop through all entries descriptions
var allEntries = Enum.GetValues(typeof(ISO639Code));
foreach (var entry in allEntries)
{
// If you will extract this as separate method and use it for search not only loop
// through the all entries - you can put here is yield return description
var currentEntry = ((ISO639Code)entry);
string description = currentEntry.GetDescription();
if (description == searchFor)
{
foundEntry = currentEntry;
break;
}
}
您有一个枚举:
public enum ISO639Code
{
Afrikaans = 1,
Albanian = 2,
Amharic = 3,
等等
创建数据库表:
ISO639Id int PK,
ISO639Code char(2)
其中ISO639Id映射到枚举的值
在代码中,您需要一个包含从数据库读取的Id和代码值的ISO630类。
(您可以加载一次,然后将其缓存在内存中。)
这种方法的美妙之处在于,它可以很容易地扩展,以便将来如果您想为每个ISO639代码存储更多信息,只需添加另一个字段即可。查看System.Globalization命名空间。您需要的功能看起来已经在那里实现了。在最坏的情况下,您可以看到在.Net framework中应用的体系结构和技术来解决一个非常类似的问题。枚举非常适合在代码中工作,因为它们确实是强类型的,并且使重构更容易。 遵循以下步骤:
描述
属性。比如:
公共枚举等参线
{
[说明(“af”)]
非洲人=0,
[说明(“am”)]
美国人=1
}public static string GetDescription(this Enum value)
{
var entries = value.ToString().Split(FlagEnumSeparatorCharacter);
var description = new string[entries.Length];
for (var i = 0; i < entries.Length; i++)
{
var fieldInfo = value.GetType().GetField(entries[i].Trim());
var attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim();
}
return String.Join(", ", description);
}
public static int GetValue(this Enum value)
{
return (int)value.GetType().GetField(value.ToString()).GetRawConstantValue();
}
public static T ToEnum<T>(this string value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Not an enum");
}
return (T)Enum.Parse(typeof(T), value, true);
}
public static T ToEnum<T>(this int value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Not an enum");
}
return (T)Enum.ToObject(typeof(T), value);
}
公共静态字符串GetDescription(此枚举值)
{
var entries=value.ToString().Split(flagnumsparatorcharacter);
变量说明=新字符串[entries.Length];
对于(var i=0;i0)?属性[0]。description:条目[i]。Trim();
}
返回字符串。Join(“,”,description);
}
公共静态int GetValue(此枚举值)
{
返回(int)value.GetType().GetField(value.ToString()).GetRawConstantValue();
}
公共静态T ToEnum(此字符串值)
{
if(typeof(T).BaseType.Name!=typeof(Enum).Name)
{
抛出新异常(“不是枚举”);
}
返回(T)Enum.Parse(typeof(T),value,true);
}
公共静态T ToEnum(此int值)
{
if(typeof(T).BaseType.Name!=typeof(Enum).Name)
{
抛出新异常(“不是枚举”);
}
返回(T)Enum.ToObject(typeof(T),value);
}
现在可以随意使用枚举。我建议使用
ISO639Code
作为类,而不是枚举:
public class ISO639Code
{
public string Value { get; set ; }
public string Code { get; set; }
public ISO639Code()
{
this.Value = "";
this.Code = "";
}
public ISO639Code(string value, string code)
: this()
{
this.Value = value;
this.Code = code;
}
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is string)
return obj.ToString().Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
if (obj is ISO639Code)
return ((ISO639Code)obj).Value.Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
}
return false;
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
}
然后让全局列表
包含所有可能的代码,要根据代码名或值查找特定代码,只需在列表中搜索即可
就我个人而言,我更喜欢这样做,而不是调整枚举。Anton,只是一个问题。如何使用此属性?i、 来自另一个班级。我认为这看起来很干净。@Sheldon您需要使用反射和
属性。GetCustomAttribute
,通常将此数据缓存在内存中的某个位置,以避免每次我与Sheldon有相同的问题时都进行计算。非常感谢@Marc Gravelt查看描述属性
:感谢malio。但我想知道的是C#,而不是.net framework命名空间。但问题是,通常有更好的方法来表示某些结构,但这完全取决于它们的使用方式。对于语言,CultureInfo类exists.true,但在许多方面,现有代码都非常可读。很明显,它是如何映射的。当然,可维护性是一个痛处,因为您可以很容易地进行交换或键入。我认为代码属性应该是只读的,因为在实体生命周期(对于这种特殊情况)有效参数时更改代码是没有意义的,这段代码是作为示例给出的,但不确定这里的全部范围。很好。那么如何将“af”直接映射到南非荷兰语呢?我应该通过*.GetDescription搜索所有枚举成员吗?是要动态分配描述还是按描述值搜索所有枚举条目?在这种情况下,您必须实现方法GetByDescription(此枚举currentEnum,字符串描述),我希望。。。ISO639编码l,m;k、 设定值(“af”);m=ISO639Code.Afrikaans;如果(k==m){messagebox.show(“equal.”);}this.To search by description value您必须实现
public class ISO639Code
{
public string Value { get; set ; }
public string Code { get; set; }
public ISO639Code()
{
this.Value = "";
this.Code = "";
}
public ISO639Code(string value, string code)
: this()
{
this.Value = value;
this.Code = code;
}
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is string)
return obj.ToString().Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
if (obj is ISO639Code)
return ((ISO639Code)obj).Value.Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
}
return false;
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
}