2013-01-21 33 views
6

在c#中,我对理解Enum有点困惑。是否有可能像使用字典一样使用Enum值对

在我的特异性的情况下,我需要像>

300秒= 5分钟

在我使用这个类的那一刻起名称值格式储存恒定值。

  • 将可能使用枚举,所以我的Enum类会看起来很喜欢?
  • 我可以存储Enum a Pair值吗?

您能否提供一份代码示例?

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; 
     } 

    } 
} 
+1

所有'0'键的意图是什么?你的意思是指定秒数? – atlaste

+0

感谢Stefan指出。我已经编辑了我的问题。 – GibboK

+2

我想你应该看看[TimeSpan](http://msdn.microsoft.com/en-us/library/system.timespan.aspx)类,而不是使用这些数字。 – Default

回答

8

你可以使用一个Tuple<int, int>作为字典键(至少与.NET> = 4)。

但是由于您确实想要存储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 ]; 
+4

TimeSpan.FromSeconds和TimeSpan .FromMinutes等而不是ctor提供了关于imo发生的更好的描述。 – atlaste

+0

必须同意斯蒂芬在这一个。然而,它作为一个很好的扩展方法是有意义的,例如'TimeSpan.FromMinutes(15).DisplayName()' – James

+0

@StefandeBruijn:是的,我只是想展示如何创建任何时间片(即一小时+30分钟)而无需计算。请注意,我使用下面的工厂方法。 –

2

如果你问你可以存储对一个枚举的整数值则是你可以如

public enum DurationSeconds 
{ 
    None = 0, 
    FiveMinutesBefore = 300, 
    FifteenMinutesBefore = 900, 
    ThirtyMinutesBefore = 1800, 
    OneHourBefore = 3600, 
    TwoHoursBefore = 7200, 
    OneDayBefore = 86400, 
    TwoDaysBefore = 172800 
} 
+3

枚举名称不能以数字开头iirc – atlaste

+0

@StefandeBruijn我已更新为使用字符串(用于速度!)。 – James

5

您可以用描述属性装饰枚举并稍后通过反射访问它们。

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; 
} 

另见:例如,

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

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

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

你可以得到说明http://www.codeproject.com/Articles/13821/Adding-Descriptions-to-your-Enumerations

+0

虽然这是可能的,但当您只是寻找名称 - 值对(就像添加第二个名称)时,我并没有真正看到添加属性的要点。对于这种情况,我会说你在过度设计。 – atlaste

+0

@StefandeBruijn绝对同意,TimSchmelter的答案可能是最好的。但问题是,“我可以使用枚举”,所以我正在说明如何。 –

+0

虽然这可能不是特定问题的最佳答案,但这是一个非常有用的想法。谢谢。 – Steven

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类型(在我的情况明确)。因为它是一个值类型,它与内存中的实数整数结构相同 - 这可能是编译器在投射时使用的。

0

与我平时所做的相反,我会添加另一个答案,即IMO是问题的答案。

您通常希望编译器在实际使用运行时检查之前尽可能多地执行检查。也就是说,在这种情况下使用枚举对获取值:

// 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值(例如,新的提醒((TimeSpanEnum)5)将失败
相关问题