C# 如何制作';枚举';有相关数据吗?

C# 如何制作';枚举';有相关数据吗?,c#,.net,asp.net-mvc,enums,C#,.net,Asp.net Mvc,Enums,我有一个投票类,它可以拥有的属性之一是投票类型。例如一致、3/4票、简单多数票等。每种类型都需要有一个与之关联的字符串来描述投票类型(如“简单多数票需要51%才能通过”等)。我需要将这些投票类型/描述与我的视图模型一起传递到我的视图,然后我可以使用它制作下拉列表 然后,当提交创建投票的表单时,我只需要将投票类型(无描述)绑定到投票模型(它是视图模型的一部分) 我使用C#的时间很短,我不太了解枚举在其中是如何工作的。也许enum不是解决这个问题的方法 public class VoteViewMo

我有一个投票类,它可以拥有的属性之一是投票类型。例如一致、3/4票、简单多数票等。每种类型都需要有一个与之关联的字符串来描述投票类型(如“简单多数票需要51%才能通过”等)。我需要将这些投票类型/描述与我的视图模型一起传递到我的视图,然后我可以使用它制作下拉列表

然后,当提交创建投票的表单时,我只需要将投票类型(无描述)绑定到投票模型(它是视图模型的一部分)

我使用C#的时间很短,我不太了解枚举在其中是如何工作的。也许enum不是解决这个问题的方法

public class VoteViewModel
{
    public VoteViewModel()
    {
        Vote = new Vote();
    }

    public Vote Vote { get; set; }
    public int EligibleVoters { get; set; }
}
这就是我要放下的地方

<section class="vote-type">
    <select name="">
        <option value="">Select Vote Type</option>
    </select>
    <section class="vote-type-info">
        <p class="vote-rules">To pass this vote, at least 51% of Eligible Voters must vote to approve it.</p>
    </section>
</section>

选择投票类型

要通过这次投票,至少51%的合格选民必须投票批准

您可以围绕枚举创建一个“常量”字典(或者更确切地说是只读静态字典,因为您无法创建常量字典)

public enum VoteType { Unanimous = 1, SimpleMajority = 2, ... }

public static readonly Dictionary<VoteType, string> VoteDescriptions = new Dictionary<VoteType, string>
{
    { VoteType.Unanimous, "Unanimous description" },
    { VoteType.SimpleMajority, "Simple majority" },
    ...
};
public enum VoteType{consensible=1,SimpleMajority=2,…}
公共静态只读字典votedDescriptions=新字典
{
{VoteType.consenous,“consenous description”},
{VoteType.SimpleMajority,“简单多数”},
...
};

我以前用过这个,它真的很方便

简而言之,它可以让您做到:

public enum MyColors{
   [Description("The Color of my skin")]
   White,
   [Description("Bulls like this color")]
   Red,
   [Description("The color of slime")]
   Green
}
然后通过调用以下命令返回描述:

String desc = GetDescription(MyColor.Green);
不过,它确实使用了反射,因此在简单性和轻微的性能损失之间有一个折衷。大多数时候我都会在表演中受到打击

public class Vote()
{
     public VoteType VoteSelectType { get; set; }
}

public enum VoteType
{
    [Display(Name = "Enter Text Here")]
    unanimous = 1,
    [Display(Name = "Enter Text Here")]
    threequatervote = 2,
    [Display(Name = "Enter Text Here")]
    simplymajority = 3
}
转到这里这几乎是你的解决方案

如果需要,可以使用枚举,但需要决定如何在枚举值和要显示的内容之间建立链接。例如,希望显示为“简单多数”的SimpleMajority枚举值。一种方法是使用Description属性和所述的helper类


但是,您可能会发现设置轻量级集合类来存储投票类型值及其描述更容易。这可以像
字典一样简单
您可能会发现这是一种更直接的方法。

因为您有
类型和
描述
,我建议您创建一个
,它将这两种类型都封装起来,而不是
枚举
。优点是可以减少更多的工作量,而且非常灵活

public class VoteType
{
   public string Name{ get; set; }
   public string Description{ get; set; }
}
现在您的
投票
类将引用此
VoteType

public class Vote
{
   ...
   public VoteType Type{ get; set; }
}
VoteViewModel
中,最好有一个包含所有
VoteType
s的类

public class VoteViewModel
{
   ...
   public IEnumerable<SelectListItem> VoteTypes{ get; set; }
}

请注意,我只显示字符串,因为它可以是任何类型。在每种情况下,如果可能,我都会提到如何扩展它以获得更多的值


使用枚举作为键 您可以将枚举类型用作字典的键(您希望是唯一的,因此在某些帮助器类中使其成为静态和只读的):

或与:

string text;
if (Dict.TryGetValue(MyEnumEmu.MyValue, out text))
{
    //It has the value
}
else
{
    //It doesn't have the value
}
通过这种方式,您可以访问与枚举值关联的字符串。然后可以公开字典,以便读取相应的值

您将需要一个复杂类型来存储多个值。只需使用自定义类型isntead的字符串。或者,如果可用,您可以使用
元组

访问
字典
可能意味着额外的麻烦,希望它不会意味着线程问题


Enum.GetName 您可以使用读取枚举值的名称:

string text = Enum.GetName(MyEnum.MyValue);
//text will have the text "MyValue"

//or
var some = MyEnum.MyValue;
string text = Enum.GetName(some);
public enum MyEnum
{
    [EnumValue("The text for MyValue")]
    MyValue = 1,
    [EnumValue("Some other text")]
    MyOtherValue = 2,
    [EnumValue("Something else")]
    YetAnotherValue = 3
}
注意:
ToString()
也可以

遗憾的是,这对于字符串以外的其他对象不起作用

此外,它还有一个缺点,即不能将任何文本放在那里(它必须是有效的标识符)


自定义属性 您必须声明一个属性类型:

[AttributeUsage(AttributeTargets.Field)]
public class EnumValueAttribute : System.Attribute 
{
    public readonly string _value;

    public string Value
    {
        get
        {
            return _value;
        }
    }

    public HelpAttribute(string value)  // value is a positional parameter
    {
        //beware: value can be null...
        // ...but we don't want to throw exceptions here
        _value = value;
    }
}
现在将属性应用于枚举:

string text = Enum.GetName(MyEnum.MyValue);
//text will have the text "MyValue"

//or
var some = MyEnum.MyValue;
string text = Enum.GetName(some);
public enum MyEnum
{
    [EnumValue("The text for MyValue")]
    MyValue = 1,
    [EnumValue("Some other text")]
    MyOtherValue = 2,
    [EnumValue("Something else")]
    YetAnotherValue = 3
}
最后,您需要读回该属性:

public static string GetValue(MyEnumenumValue)
{
    FieldInfo fiendInfo = typeof(MyEnum).GetField(enumValue.ToString());
    if (!ReferenceEquals(fiendInfo, null))
    {
        object[] attributes = fieldInfo.GetCustomAttributes(typeof(EnumValueAttribute), true);
        if (!ReferenceEquals(attributes, null) && attributes.Length > 0)
        {
            return ((EnumValueAttribute)attributes[0]).Value;
        }
    }
    //Not valid value or it didn't have the attribute
    return null;
}
现在你可以称之为:

string text = GetValue(MyEnum.MyValue);
//text will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text = GetValue(some);
您可以向属性类添加更多字段,并使用它们传递可能需要的任何其他值

但这需要反射,如果您在沙箱中运行,它可能不可用。它还将每次检索属性,在过程中创建一些短期对象


模拟枚举 您可以使用没有公共构造函数并公开自身静态只读实例的密封类来模拟枚举:

public sealed class MyEnumEmu
{
    private static readonly string myValue = new MyEnumEmu("The text for MyValue");
    private static readonly string myOtherValue = new MyEnumEmu("Some other text");
    private static readonly string yetAnotherValue = new MyEnumEmu("Something else");

    public static MyEnumEmu MyValue
    {
        get
        {
            return myValue;
        }
    }

    public static MyEnumEmu MyOtherValue 
    {
        get
        {
            return myOtherValue;
        }
    }

    public static MyEnumEmu YetAnotherValue
    {
        get
        {
            return yetAnotherValue;
        }
    }

    private string _value;

    private MyEnumEmu(string value)
    {
        //Really, we are in control of the callers of this constructor...
        //... but, just for good measure:
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }
        else
        {
            _value = value;
        }
    }

    public string Value
    {
        get
        {
            return _value;
        }
    }
}
一如既往地使用它:

var some = MyEnumEmu.MyValue;
并访问关联的值:

string text = Dict[MyEnumEmu.MyValue];
string text = MyEnumEmu.MyValue.Value;
//text will have the text "MyValue"
//or
string text = some.Value;
这是最灵活的,您可以使用复杂类型而不是字符串,也可以添加额外的字段来传递多个值


但是。。。它实际上不是枚举。

您可能希望使用自定义属性。如何获取枚举的自定义属性值?“简单多数需要51%才能通过”:这是不正确的。正确的说法是“简单多数需要超过50%才能通过。”这还有一个额外的优点,就是将来可以本地化。唯一的缺点是,如果其中一项发生变化,说明和枚举项很容易失去同步…@Blueberry very true;可能通过为枚举项指定明确的值(将其添加到答案中)来缓解。对于
public static readonly Dictionary voteddescriptions=enum.GetValues(typeof(T)).Cast().ToDictionary(x=>x,x=>”),可能会稍微有点防御性
并更新静态构造函数中的值部分。至少您不会错过为详细答案添加枚举值..+1。关于密封类方法的一个注意事项是,您失去了枚举的强类型特性的一些好处。在您的情况下,如果(text==“asd”)
字符串text=MyEnumEmu.MyValue.Value,我可以这样做;text=SomeOtherEnum.MyValue.Value
等。。但不可能使用枚举(没有一些显式强制转换)。还有字典,这是一个很好的机会