6

在 c# 中,我对理解 Enum 有点困惑。

在我的特定情况下,我需要以名称值格式存储常量值,例如>

300 秒 = 5 分钟

目前我使用这个类。

  • 可以改用 Enum,所以我的 Enum 类看起来像吗?
  • 我可以在枚举中存储一对值吗?

你能给我一个代码示例吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyWebSite.Models
{
    public class Reminders
    {
        private sortedDictionary<int, string> remindersValue = new SortedDictionary<int, string>();

        // We are settign the default values using the Costructor
        public Reminders()
        {
            remindersValue.Add(0, "None");
            remindersValue.Add(300, "5 minutes before");
            remindersValue.Add(900, "15 minutes before");
        }

        public SortedDictionary<int, string> GetValues()
        {
            return remindersValue;
        }

    }
}
4

5 回答 5

8

您可以使用Tuple<int, int>as 字典键(至少在 .NET >= 4 中)。

但是由于您实际上想要存储 a TimeSpan,因此将其用作键。

private static Dictionary<TimeSpan, string> TimeSpanText = new Dictionary<TimeSpan, string>();

static Reminders()
{
    TimeSpanText.Add(TimeSpan.Zero, "None");
    TimeSpanText.Add(TimeSpan.FromMinutes( 5 ), "5 minutes before");
    TimeSpanText.Add(TimeSpan.FromMinutes( 15 ), "15 minutes before");
    TimeSpanText.Add(TimeSpan.FromMinutes( 30 ), "30 minutes before");
    TimeSpanText.Add(TimeSpan.FromHours( 1 ), "1 hour before");
    // ....
}

public static string DisplayName(TimeSpan ts)
{
    string text;
    if (TimeSpanText.TryGetValue(ts, out text))
        return text;
    else
         throw new ArgumentException("Invalid Timespan", "ts");
}

您可以通过以下方式获得翻译:

var quarter = TimeSpan.FromMinutes(15);
string text = TimeSpanText[ quarter ];
于 2013-01-21T09:08:14.397 回答
5

您可以使用描述属性装饰您的枚举,并在以后通过反射访问它们。例如,

enum ReminderTimes
{
    [Description("None")]
    None = 0,

    [Description("5 minutes before")]
    FiveMinutesBefore = 300,

    [Description("15 minutes before")]
    FifteenMinutesBefore = 900
}

您可以通过以下方式获取描述:

public static string GetDescription(this Enum value)
{            
    FieldInfo field = value.GetType().GetField(value.ToString());

    DescriptionAttribute attribute
            = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
                as DescriptionAttribute;

    return attribute == null ? value.ToString() : attribute.Description;
}

另请参阅: http: //www.codeproject.com/Articles/13821/Adding-Descriptions-to-your-Enumerations

于 2013-01-21T09:10:01.043 回答
3

枚举实际上是一个命名的整数类型。例如

public enum Foo : int 
{
   SomeValue = 100,
}

这意味着您创建了一个类型为“int”和一些值的 Foo 枚举。我个人总是明确说明正在发生的事情,但 c# 隐含地将其设为“int”类型(32 位 int)。

您可以使用任何名称作为枚举名称,并且可以使用 Enum.IsDefined 检查它是否是有效的枚举(例如检查 300 是否是有效的枚举名称)。

更新

好吧,说实话,这并不是 100% 正确的。此更新只是为了展示幕后实际发生的事情。枚举是一种值类型,其字段充当名称。例如,上面的枚举实际上是:

public struct Foo 
{ 
    private int _value;
    public static Foo SomeValue { get { return new Foo() { _value = 100 }; } }
}

请注意,'int' 是 int 的类型(在我的例子中是显式的)。因为它是一种值类型,所以它与内存中的实整数具有相同的结构——这可能是编译器在进行强制转换时使用的结构。

于 2013-01-21T09:13:12.743 回答
2

如果您问是否可以针对枚举存储整数值,那么可以,例如

 public enum DurationSeconds
 {
     None = 0,
     FiveMinutesBefore = 300,
     FifteenMinutesBefore = 900,
     ThirtyMinutesBefore = 1800,
     OneHourBefore = 3600,
     TwoHoursBefore = 7200,
     OneDayBefore = 86400,
     TwoDaysBefore = 172800
 }
于 2013-01-21T09:08:29.807 回答
0

与我通常做的相反,我将添加另一个答案,即 IMO 问题的答案。

您通常希望编译器在实际使用运行时检查之前尽可能多地进行检查。这意味着在这种情况下使用 Enum 获取值:

// provides a strong type when using values in memory to make sure you don't enter incorrect values
public enum TimeSpanEnum : int
{
    Minutes30 = 30,
    Minutes60 = 60,
}

public class Reminders
{
    static Reminders()
    {
        names.Add(TimeSpanEnum.Minutes30, "30 minutes");
        names.Add(TimeSpanEnum.Minutes60, "60 minutes");
    }

    public Reminders(TimeSpanEnum ts)
    {
        if (!Enum.IsDefined(typeof(TimeSpanEnum), ts))
        {
            throw new Exception("Incorrect value given for time difference");
        }
    }

    private TimeSpanEnum value;
    private static Dictionary<TimeSpanEnum, string> names = new Dictionary<TimeSpanEnum, string>();

    public TimeSpan Difference { get { return TimeSpan.FromSeconds((int)value); } }
    public string Name { get { return names[value]; } }

}

在创建这样的程序时,该语言可以通过以下几种方式帮助您:

  • 您不能使用未定义的时间跨度
  • 准确地说,它只初始化字典一次:当类型被构造时
  • Enum.IsDefined 确保您不使用不正确的 int 值(例如 new Reminders((TimeSpanEnum)5) 将失败。
于 2013-01-21T09:41:38.117 回答