2013-01-21 12 views
6

In C# Sono un po 'perplesso per capire Enum.È possibile utilizzare Enum con valori Coppia come dizionario

Nel mio caso specif avrei bisogno di negozio di valore costante in un formato Nome valore come>

300 secondi = 5 minuti

Al momento io uso questa classe.

  • Sarebbe possibile utilizzare Enum invece, quindi la classe Enum sarebbe simile al Mi piace?
  • Posso memorizzare in un Enum un valore di coppia?

Potrebbe fornire un esempio di codice?

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

Qual è l'intento di tutti i tasti "0"? Intendi specificare il numero di secondi? – atlaste

+0

Grazie Stefan per avermelo fatto notare. Ho fatto una modifica alla mia domanda. – GibboK

+2

Penso che dovresti guardare la classe [TimeSpan] (http://msdn.microsoft.com/en-us/library/system.timespan.aspx) invece di usare quei numeri. – Default

risposta

8

È possibile utilizzare un Tuple<int, int> chiave come dizionario (almeno con .NET> = 4).

Ma dal momento che in realtà si desidera memorizzare un TimeSpan, utilizzarlo come chiave.

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

È possibile ottenere la traduzione in questo modo:

var quarter = TimeSpan.FromMinutes(15); 
string text = TimeSpanText[ quarter ]; 
+4

TimeSpan.FromSeconds e TimeSpan .FromMinutes, eccetera, il Ctor fornisce una descrizione migliore di ciò che sta accadendo. – atlaste

+0

Sono d'accordo con Stefan su questo. Tuttavia, avrebbe senso come un bel metodo di estensione, ad es. 'TimeSpan.FromMinutes (15) .DisplayName()' – James

+0

@StefandeBruijn: Sì, volevo solo mostrare come creare qualsiasi timespace (ad esempio un'ora + 30 minuti) senza dover calcolare. Nota che ho usato il metodo di fabbrica qui sotto. –

2

Se ti stai chiedendo si può memorizzare un valore intero contro un enum, allora sì, si può per esempio

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

I nomi Enum non possono iniziare con un numero iirc – atlaste

+0

@StefandeBruijn Ho aggiornato per usare invece le stringhe (numeri usati per la velocità!). – James

5

È possibile decorare l'enumerazione con gli attributi di descrizione e accedervi in ​​seguito tramite la riflessione. Ad esempio,

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

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

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

è possibile ottenere la descrizione da:

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

Vedi anche: http://www.codeproject.com/Articles/13821/Adding-Descriptions-to-your-Enumerations

+0

Mentre è possibile, non vedo il punto di aggiungere attributi quando stai solo cercando una coppia nome-valore (è come aggiungere un secondo nome). Per questo scenario, direi che stai sovradimensionando. – atlaste

+0

@StefandeBruijn Decisamente d'accordo e la risposta di TimSchmelter è probabilmente la migliore. La domanda era, tuttavia, "potrei usare un enum" così stavo illustrando come. –

+0

Anche se forse non è la risposta migliore per la domanda specifica, è un'idea molto utile. Grazie. – Steven

3

un enum è in realtà un tipo intero di nome. Per esempio.

public enum Foo : int 
{ 
    SomeValue = 100, 
} 

che significa che si crea un'enumerazione di Foo con il tipo 'int' e qualche valore. Personalmente lo faccio sempre esplicitamente per mostrare cosa sta succedendo, ma C# lo rende implicitamente il tipo 'int' (int 32 bit).

È possibile utilizzare qualsiasi nome per i nomi enum e può controllare se è un enum valido utilizzando Enum.IsDefined (ad esempio per verificare se 300 è un nome enum valido).

aggiornamento

Va bene, in realtà questo non è corretta al 100% per essere onesti. Questo aggiornamento serve solo per mostrare cosa sta realmente accadendo sotto il cofano. Un enum è un tipo di valore con campi che fungono da nomi. Per esempio. Quanto sopra è in realtà enum:

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

Si noti che la 'int' è il tipo di int (nel mio caso esplicito). Poiché è un tipo di valore, ha la stessa struttura di un intero reale nella memoria, che probabilmente è ciò che viene utilizzato dal compilatore durante il casting.

0

Contrariamente a quello che faccio di solito, aggiungerò un'altra risposta, che è la risposta IMO al problema.

In genere si desidera che il compilatore esegua il maggior controllo possibile prima di utilizzare effettivamente il controllo in fase di esecuzione. Ciò significa che in questo caso utilizzando Enum di per i valori che ottengono:

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

} 

Quando si crea il programma come questo, la lingua che aiuta in un paio di modi:

  • non è possibile utilizzare timespans che non sono definiti
  • si inizializza il dizionario solo una volta, per l'esattezza:. quando il tipo è costruito
  • L'Enum.IsDefined fa in modo non usate un valore int errato (ad esempio, nuovi promemoria ((TimeSpanEnum) 5) non riuscirà
Problemi correlati