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

使用用户友好的字符串枚举ToString

如何解决《使用用户友好的字符串枚举ToString》经验,为你挑选了10个好方法。

我的枚举包含以下值:

private enum PublishStatusses{
    NotCompleted,
    Completed,
    Error
};

我希望能够以用户友好的方式输出这些值.
我不需要能够再次从字符串变为值.



1> 小智..:

我用扩展方法做到这一点:

public enum ErrorLevel
{
  None,
  Low,
  High,
  SoylentGreen
}

public static class ErrorLevelExtensions
{
  public static string ToFriendlyString(this ErrorLevel me)
  {
    switch(me)
    {
      case ErrorLevel.None:
        return "Everything is OK";
      case ErrorLevel.Low:
        return "SNAFU, if you know what I mean.";
      case ErrorLevel.High:
        return "Reaching TARFU levels";
      case ErrorLevel.SoylentGreen:
        return "ITS PEOPLE!!!!";
      default:
        return "Get your damn dirty hands off me you FILTHY APE!";
    }
  }
}


我看到的问题是你经常写这些扩展方法.使用属性机制,它是一种简单的装饰方法,只能调用一个方法.
在我看来,最好允许`default` case实现返回`me.ToString()`,并且只为你想要覆盖的枚举值提供switch case语句.在你的例子中,我得到的是它们都不同但在实际使用情况下,我怀疑大多数单字枚举值都足够了,你只会为多字枚举值提供覆盖.
这比属性答案要清晰得多.太好了!
不明白你的意思?
@pennyrave:呃.期望找到并使用DisplayNameAttribute和DescriptionAttribute的许多UI组件.实际上,现在,我使用这些和扩展方法来轻松获取这些值.

2> Ray Booysen..:

我使用DescriptionSystem.ComponentModel命名空间中的属性.只需装饰枚举:

private enum PublishStatusValue
{
    [Description("Not Completed")]
    NotCompleted,
    Completed,
    Error
};

然后使用此代码检索它:

public static string GetDescription(this T enumerationValue)
    where T : struct
{
    Type type = enumerationValue.GetType();
    if (!type.IsEnum)
    {
        throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
    }

    //Tries to find a DescriptionAttribute for a potential friendly name
    //for the enum
    MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
    if (memberInfo != null && memberInfo.Length > 0)
    {
        object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attrs != null && attrs.Length > 0)
        {
            //Pull out the description value
            return ((DescriptionAttribute)attrs[0]).Description;
        }
    }
    //If we have no description attribute, just return the ToString of the enum
    return enumerationValue.ToString();
}


我怀疑使用这个解决方案中描述的反射会有很大的性能损失.Will使用ToFriendlyString扩展方法的方法的代码更容易理解,其性能也应该非常快.
这个例子更容易阅读.http://stackoverflow.com/questions/1415140/can-my-enums-have-friendly-names
它确实意味着每个枚举都需要它自己的扩展方法.这是更普遍的使用,需要更多的工作,但你可能想要在我们决定性能之前量化"快速"的含义.
如果您希望向用户显示友好字符串,则@petar可以正常工作.MY_TYPE将具有下划线并且不可自定义.

3> annakata..:

也许我错过了一些东西,但Enum.GetName出了什么问题?

public string GetName(PublishStatusses value)
{
    return Enum.GetName(typeof(PublishStatusses), value)
}

编辑:对于用户友好的字符串,您需要通过.resource来完成国际化/本地化,并且使用基于枚举键的固定键而不是相同的装饰器属性可能更好.


我返回枚举的文字值,而不是一些用户友好的值.
为MyEnum.ToString()+1作为本地化的资源键.多年来我一直这样做
oic - 这是一个非常大的案例,你必须通过基于此值的字符串资源库,因为替代(装饰器属性)将不支持I18N

4> bjrichardson..:

我创建了一个反向扩展方法,将描述转换回枚举值:

public static T ToEnumValue(this string enumerationDescription) where T : struct
{
    var type = typeof(T);

    if (!type.IsEnum)
        throw new ArgumentException("ToEnumValue(): Must be of enum type", "T");

    foreach (object val in System.Enum.GetValues(type))
        if (val.GetDescription() == enumerationDescription)
            return (T)val;

    throw new ArgumentException("ToEnumValue(): Invalid description for enum " + type.Name, "enumerationDescription");
}


对不起,谢谢你们的帮助!虽然因为这是一个问答网站,但答案*应该是尝试直接回答问题.问题特别指出"*我不需要再次从字符串变为值.*"再一次,谢谢!
感谢积极的批评.对网站来说,了解其文化和细微差别总是很困难.我很高兴有像你这样的人让新人们直截了当.再一次,谢谢你不要倾倒新人.
@Jesse 4年后,有人很高兴在这里找到bjrichardson代码!这可能是一个问答网站,但这并不意味着问题在被回答之后就已经死了.

5> Noldorin..:

这里最简单的解决方案是使用自定义扩展方法(至少在.NET 3.5中 - 您可以将其转换为早期框架版本的静态帮助方法).

public static string ToCustomString(this PublishStatusses value)
{
    switch(value)
    {
        // Return string depending on value.
    }
    return null;
}

我在这里假设您想要返回除枚举值的实际名称之外的其他内容(您可以通过简单地调用ToString获得).



6> Lemmy..:

另一篇文章是Java.您不能在C#中将方法放在枚举中.

做这样的事情:

PublishStatusses status = ...
String s = status.ToString();

如果要为枚举值使用不同的显示值,可以使用"属性"和"反射".


那么这对他的特定枚举来说是最简单的解决方案
toString在所有情况下都不安全 - 具有相同值的多个条目(例如整数枚举)的枚举将返回第一个匹配值的键,而不是测试项的键,这就是首选Enum.GetName的原因

7> Milan Švec..:

最简单的方法就是将此扩展类包含在项目中,它将与项目中的任何枚举一起使用:

public static class EnumExtensions
{
    public static string ToFriendlyString(this Enum code)
    {
        return Enum.GetName(code.GetType(), code);
    }
}

用法:

enum ExampleEnum
{
    Demo = 0,
    Test = 1, 
    Live = 2
}

...

ExampleEnum ee = ExampleEnum.Live;
Console.WriteLine(ee.ToFriendlyString());


如果enum已经很好地命名,则不需要任何扩展方法.只需使用现有的ToString()方法.`string result ="结果:"+ ee;`
此答案和所有注释都忽略了对扩展描述的原始请求.你们完全错过了返回默认ToString值以外的东西的练习.我不会在这里给出这个答案的所有注释,但我确实想要.
关于为什么这个评论不是被接受的,或者最受欢迎的 - 没有反映,没有不必要的属性,这对于简单的情况来说是理想的,因为枚举已经被很好地命名了.您可以更进一步,并允许在返回之前在大写字母之间添加空格,"我的枚举".

8> samis..:

一些其他更原始的选项可以避免类/引用类型:

数组方法

嵌套的struct方法

数组方法

private struct PublishStatusses
{
    public static string[] Desc = {
        "Not Completed",
        "Completed",
        "Error"
    };

    public enum Id
    {
        NotCompleted = 0,
        Completed,
        Error
    };
}

用法

string desc = PublishStatusses.Desc[(int)PublishStatusses.Id.Completed];

嵌套的struct方法

private struct PublishStatusses
{
    public struct NotCompleted
    {
        public const int Id = 0;
        public const string Desc = "Not Completed";
    }

    public struct Completed
    {
        public const int Id = 1;
        public const string Desc = "Completed";
    }

    public struct Error
    {
        public const int Id = 2;
        public const string Desc = "Error";
    }            
}

用法

int id = PublishStatusses.NotCompleted.Id;
string desc = PublishStatusses.NotCompleted.Desc;

更新(03/09/2018)

扩展方法与上述第一种技术的混合.

我更喜欢将枚举定义为"属于"(最接近其原始来源而不是某些常见的全局命名空间).

namespace ViewModels
{
    public class RecordVM
    {
        //public enum Enum { Minutes, Hours }
        public struct Enum
        {
            public enum Id { Minutes, Hours }
            public static string[] Name = { "Minute(s)", "Hour(s)" };
        }
    }
}

扩展方法似乎适用于公共区域,枚举的"本地化"定义现在使扩展方法更加冗长.

namespace Common
{
    public static class EnumExtensions
    {
        public static string Name(this RecordVM.Enum.Id id)
        {
            return RecordVM.Enum.Name[(int)id];
        }
    }   
}

枚举的用法示例及其扩展方法.

namespace Views
{
    public class RecordView 
    {
        private RecordDataFieldList _fieldUnit;

        public RecordView()
        {
            _fieldUnit.List = new IdValueList
            {            
                new ListItem((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
                new ListItem((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name())
            };
        }

        private void Update()
        {    
            RecordVM.Enum.Id eId = DetermineUnit();

            _fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value;
        }
    }
}

注意:我实际上决定消除Enum包装器(和Name数组),因为名称字符串最好来自资源(即配置文件或数据库)而不是硬编码,因为我最终将扩展方法放在ViewModels命名空间(只是在另一个"CommonVM.cs"文件中).此外,整个.Id事情变得分散注意力和繁琐.

namespace ViewModels
{
    public class RecordVM
    {
        public enum Enum { Minutes, Hours }
        //public struct Enum
        //{
        //    public enum Id { Minutes, Hours }
        //    public static string[] Name = { "Minute(s)", "Hour(s)" };
        //}
    }
}

CommonVM.cs

//namespace Common
namespace ViewModels
{
    public static class EnumExtensions
    {
        public static string Name(this RecordVM.Enum id)
        {
            //return RecordVM.Enum.Name[(int)id];
            switch (id)
            {
                case RecordVM.Enum.Minutes: return "Minute(s)";                    
                case RecordVM.Enum.Hours: return "Hour(s)";
                default: return null;
            }
        }
    }   
}

枚举的用法示例及其扩展方法.

namespace Views
{
    public class RecordView 
    {
        private RecordDataFieldList _fieldUnit

        public RecordView()
        {
            _fieldUnit.List = new IdValueList
            {            
                new ListItem((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
                new ListItem((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name())
            };
        }

        private void Update()
        {    
            RecordVM.Enum eId = DetermineUnit();

            _fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value;
        }
    }
}



9> Konrad Kokos..:

您可以使用Humanizer包和Humanize Enums possiblity.一个例子:

enum PublishStatusses
{
    [Description("Custom description")]
    NotCompleted,
    AlmostCompleted,
    Error
};

那么你可以Humanize直接在枚举上使用扩展方法:

var st1 = PublishStatusses.NotCompleted;
var str1 = st1.Humanize(); // will result in Custom description

var st2 = PublishStatusses.AlmostCompleted;
var str2 = st2.Humanize(); // will result in Almost completed (calculated automaticaly)



10> 小智..:

关于Ray Booysen,代码中存在一个错误:使用用户友好字符串的Enum ToString

您需要在枚举值上考虑多个属性.

public static string GetDescription(this object enumerationValue)
            where T : struct
    {
        Type type = enumerationValue.GetType();
        if (!type.IsEnum)
        {
            throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
        }

        //Tries to find a DescriptionAttribute for a potential friendly name
        //for the enum
        MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
        if (memberInfo != null && memberInfo.Length > 0)
        {
            object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attrs != null && attrs.Length > 0 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null)
            {
                //Pull out the description value
                return ((DescriptionAttribute)attrs.Where(t=>t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description;
            }
        }
        //If we have no description attribute, just return the ToString of the enum
        return enumerationValue.ToString();


省略对多个描述属性的检查是故意的.如果枚举有两个,并且你用来生成描述,我想认为这是一个特例.我认为实际的错误是我没有使用Single()来抛出异常.否则整个方法签名毫无意义.GetDescription()?哪个描述?聚合?
推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有