当前位置:  开发笔记 > 编程语言 > 正文

将枚举与C#中的字符串相关联

如何解决《将枚举与C#中的字符串相关联》经验,为你挑选了10个好方法。

我知道以下是不可能的,因为它必须是一个int

enum GroupTypes
{
    TheGroup = "OEM",
    TheOtherGroup = "CMB"
}

从我的数据库中我得到一个包含不全面代码的字段(OEM和CMB).我想把这个领域变成一个枚举或其他可以理解的东西.因为目标是可读性,所以解决方案应该简洁.
我还有其他选择吗?



1> Even Mien..:

我喜欢在类中使用属性而不是方法,因为它们看起来更像枚举.

以下是Logger的示例:

public class LogCategory
{
    private LogCategory(string value) { Value = value; }

    public string Value { get; set; }

    public static LogCategory Trace   { get { return new LogCategory("Trace"); } }
    public static LogCategory Debug   { get { return new LogCategory("Debug"); } }
    public static LogCategory Info    { get { return new LogCategory("Info"); } }
    public static LogCategory Warning { get { return new LogCategory("Warning"); } }
    public static LogCategory Error   { get { return new LogCategory("Error"); } }
}

类型安全的字符串值作为参数传递:

public static void Write(string message, LogCategory logCategory)
{
    var log = new LogEntry { Message = message };
    Logger.Write(log, logCategory.Value);
}

用法:

Logger.Write("This is almost like an enum.", LogCategory.Info);


为了我自己的使用,我扩展了这个概念,重写了`ToString`方法以返回`Value`.然后在字符串中提供隐式转换运算符.`public static implicit operator String(LogCategory category){返回值; }`.
在交换机箱中使用它怎么样?
我唯一能想到的是,它会慢一点,但在大多数情况下这可以忽略不计.它在编辑器中不会有完全相同的行为.EG:切换这个不会自动填写每种可能性的情况.除了那些小问题,我认为这可能是一个相当简单的解决方案.
@ArnisL.仅作为键工作是不够的,您需要重写Equals()和GetHashCode(),并且您希望将Value属性设置器设为私有.不过,这不是一个枚举.
并且很容易使用Dictionary 作为开关.:)
明智的决定。我将“值”设置器设为私有。
现在使用c#6,您可以使它更加整洁,`public static string Trace =>“ Trace”;`。

2> Glennular..:

您还可以使用扩展模型:

public enum MyEnum
{
    [Description("String 1")]
    V1= 1,
    [Description("String 2")]
    V2= 2
} 

您的扩展类

public static class MyEnumExtensions
{
    public static string ToDescriptionString(this MyEnum val)
    {
        DescriptionAttribute[] attributes = (DescriptionAttribute[])val
           .GetType()
           .GetField(val.ToString())
           .GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : string.Empty;
    }
} 

用法:

MyEnum myLocal = MyEnum.V1;
print(myLocal.ToDescriptionString());


我不禁要想,从性能的角度来看,每次要显示枚举时都要反映枚举听起来有些痛苦!
另请参阅http://stackoverflow.com/questions/4367723/get-enum-from-description-attribute以获取其他扩展名,并通过描述从字符串到enum.
@Liath - `.ToString()`已经使用了反射,因此你不会因为这种方法而失去任何东西,并获得可读性
为了使通用,使用`public static string ToDescriptionString(this Enum ...`,即不显式键入`MyEnum`。

3> rpattabi..:

如何使用带常量的静态类?客户端代码看起来与枚举没有什么不同.

static class GroupTypes
{
  public const string TheGroup = "OEM";
  public const string TheOtherGroup = "CMB";
}

void DoSomething(string groupType)
{
  if(groupType == GroupTypes.TheGroup)
  {
    // Be nice
  }  
  else if (groupType == GroupTypes.TheOtherGroup)
  {
    // Continue to be nice
  }
  else
  {
    // unexpected, throw exception?
  }
}


静态类型不能用作参数.
同意.我无法看到更复杂的解决方案背后的目的,除非能够切换生成的"枚举".
这些常量需要是内部的或公共的才能实现

4> casperOne..:

您可以向枚举中的项添加属性,然后使用反射从属性中获取值.

您必须使用"field"说明符来应用属性,如下所示:

enum GroupTypes
{
    [field:Description("OEM")]
    TheGroup,

    [field:Description("CMB")]
    TheOtherGroup
}

然后,您将反映枚举类型的静态字段(在本例中为GroupTypes),并DescriptionAttribute使用反射获取您要查找的值:

public static DescriptionAttribute GetEnumDescriptionAttribute(
    this T value) where T : struct
{
    // The type of the enum, it will be reused.
    Type type = typeof(T);

    // If T is not an enum, get out.
    if (!type.IsEnum) 
        throw new InvalidOperationException(
            "The type parameter T must be an enum type.");

    // If the value isn't defined throw an exception.
    if (!Enum.IsDefined(type, value))
        throw new InvalidEnumArgumentException(
            "value", Convert.ToInt32(value), type);

    // Get the static field for the value.
    FieldInfo fi = type.GetField(value.ToString(), 
        BindingFlags.Static | BindingFlags.Public);

    // Get the description attribute, if there is one.
    return fi.GetCustomAttributes(typeof(DescriptionAttribute), true).
        Cast().SingleOrDefault();
}

DescriptionAttribute如果您希望能够确定属性是否应用,我选择返回上面的内容.



5> 小智..:

你可以很容易地做到这一点.使用以下代码.

enum GroupTypes
{
   OEM,
   CMB
};

然后,当您想要获取每个枚举元素的字符串值时,只需使用以下代码行.

String oemString = Enum.GetName(typeof(GroupTypes), GroupTypes.OEM);

我以前成功地使用过这个方法,并且我还使用了一个常量类来保存​​字符串常量,两者都运行得很好,但我更喜欢这个.


不,这只是获取枚举值的名称,而不是将字符串赋值给枚举值.OP的目标是使字符串与枚举值不同,例如:TheGroup ="OEM",TheOtherGroup ="CMB".
我同意@Tim的评论,这不是*OP正在尝试做什么.如果您想知道这是一个什么用例,请考虑设备将字符串作为命令的情况,但也需要一个"人类可读"的命令版本.我需要将"更新固件"之类的内容与"UPDATEFW"命令联系起来.

6> darasd..:

尝试将常量添加到静态类.你没有最终得到一个类型,但你有可读的,有组织的常量:

public static class GroupTypes {

    public const string TheGroup = "OEM";
    public const string TheOtherGroup = "CMB";

}


很难从代码返回到描述性名称。您将必须在所有const字段上使用反射来搜索匹配项。

7> Dave Van den..:

为包含以下内容的数据库创建第二个枚举:

enum DBGroupTypes
{
    OEM = 0,
    CMB = 1
}

现在,您可以使用Enum.Parse从字符串"OEM"和"CMB"中检索正确的DBGroupTypes值.然后,您可以将这些转换为int,并从您希望在模型中进一步使用的右枚举中检索正确的值.


与使用属性和反射相反?

8> C. Ross..:

使用课程.

编辑:更好的例子

class StarshipType
{
    private string _Name;
    private static List _StarshipTypes = new List();

    public static readonly StarshipType Ultralight = new StarshipType("Ultralight");
    public static readonly StarshipType Light = new StarshipType("Light");
    public static readonly StarshipType Mediumweight = new StarshipType("Mediumweight");
    public static readonly StarshipType Heavy = new StarshipType("Heavy");
    public static readonly StarshipType Superheavy = new StarshipType("Superheavy");

    public string Name
    {
        get { return _Name; }
        private set { _Name = value; }
    }

    public static IList StarshipTypes
    {
        get { return _StarshipTypes; }
    }

    private StarshipType(string name, int systemRatio)
    {
        Name = name;
        _StarshipTypes.Add(this);
    }

    public static StarshipType Parse(string toParse)
    {
        foreach (StarshipType s in StarshipTypes)
        {
            if (toParse == s.Name)
                return s;
        }
        throw new FormatException("Could not parse string.");
    }
}



9> azamsharp..:

这是我用来将枚举值作为字符串的扩展方法.首先是枚举.

public enum DatabaseEnvironment
{
    [Description("AzamSharpBlogDevDatabase")]
    Development = 1, 
    [Description("AzamSharpBlogQADatabase")]
    QualityAssurance = 2, 
    [Description("AzamSharpBlogTestDatabase")] 
    Test = 3
}

Description属性来自System.ComponentModel.

这是我的扩展方法:

public static string GetValueAsString(this DatabaseEnvironment environment) 
{
    // get the field 
    var field = environment.GetType().GetField(environment.ToString());
    var customAttributes = field.GetCustomAttributes(typeof (DescriptionAttribute), false);

    if(customAttributes.Length > 0)
    {
        return (customAttributes[0] as DescriptionAttribute).Description;  
    }
    else
    {
        return environment.ToString(); 
    }
}

现在,您可以使用以下代码访问枚举作为字符串值:

[TestFixture]
public class when_getting_value_of_enum
{
    [Test]
    public void should_get_the_value_as_string()
    {
        Assert.AreEqual("AzamSharpBlogTestDatabase",DatabaseEnvironment.Test.GetValueAsString());  
    }
}



10> Luis Orantes..:

处理问题的另一种方法是使用枚举和字符串数组,将枚举值与字符串列表进行映射:

public enum GroupTypes
{
    TheGroup  = 0,
    TheOtherGroup 
}

string[] GroupTypesStr = {
    "OEM",
    "CMB"
};

你可以使用这样的东西:

Log.Write(GroupTypesStr[(int)GroupTypes.TheOtherGroup]);

它会提示CMB

优点:

    简单而干净的代码.

    高性能(特别是与那些使用类的方法相比)

缺点:

    在编辑时容易搞乱列表,但是对于一个简短的列表是可以的.

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有