2010-01-21 13 views
13

Dati i seguenti enum:C#: esiste un modo per classificare le enumerazioni?

public enum Position 
    { 
     Quarterback, 
     Runningback, 
     DefensiveEnd, 
     Linebacker 
    }; 

E 'possibile classificare le costanti denominate, in modo tale che avrei potuto segnare 'Quarterback' e 'Runningback' come posizioni offensive e 'defensive end' e 'Linebacker' come posizioni difensive?

+0

E 'una domanda interessante, anche se si sta cercando enumerazioni abuso, ho una domanda in cambio ... Perché non utilizza un giocatore di classe con proprietà sia per la posizione e se sono sulla squadra difensiva o offensiva? – Lazarus

risposta

7

Perché non Bacio:

class PlayerPosition { 
    public enum Position { 
     Quarterback, 
     Runningback, 
     DefensiveEnd, 
     Linebacker 
    } 

    public enum Type { 
     Offense, 
     Defense 
    } 


    public static Type GetTypeForPosition(Position position) { 
     switch (position) { 
      case Quarterback: 
      case Runningback: 
       return Type.Offense; 
      case DefensiveEnd: 
      case Linebacker: 
       return Type.Defense; 

     } 
    } 
} 
+2

Si potrebbe voler usare un nome enum diverso da Type, con System.Type in giro e tutto. Disambigliandosi ogni volta che lo usi può essere davvero fastidioso. :) – GeReV

21

È possibile utilizzare gli attributi:

public enum Position 
{ 
    [OffensivePosition] 
    Quarterback, 
    [OffensivePosition] 
    Runningback, 
    [DefensivePosition] 
    DefensiveEnd, 
    [DefensivePosition] 
    Linebacker 
}; 

E poi verificare la presenza di IsDefined su un adeguato FieldInfo. La sintassi non è molto bella, ma si può gettare in un paio di metodi di estensione per rendere le cose più gestibile:

public static bool IsOffensivePosition(PositionType pt) 
{ 
    return typeof(PositionType).GetField(Enum.GetName(typeof(PositionType), pt)). 
     IsDefined(typeof(OffensivePositionAttribute), false); 
} 
+1

+1 ho usato questo metodo in una situazione simile, ma ho scoperto che arrivare agli attributi è piuttosto doloroso nel caso di enumerazioni –

+0

Non è necessariamente doloroso ... puoi creare un metodo di estensione per recuperare l'attributo , e riutilizzalo ogni volta che ne hai bisogno –

+0

Già dato il mio +1, anche se trovo la riflessione a volte un metodo piuttosto costoso per tale follia. =) –

5

si potrebbe usare Flags

[Flags] 
public enum Position 
    { 
     Quarterback = 1, 
     Runningback = 2, 
     DefensiveEnd = 4, 
     Linebacker = 8, 

     OffensivePosition = Quarterback | Runningback, 
     DefensivePosition = Linebacker | DefensiveEnd, 

    }; 

    //strictly for example purposes 
    public bool isOffensive(Position pos) 
    { 
     return !((pos & OffensivePosition) == pos); 
    } 
+1

Desiderate chiarire i vostri pensieri su come Flags potrebbe risolvere la domanda degli utenti? –

+2

Quando si utilizza '[Flag]', è necessario specificare anche le costanti di enumerazione in potenze di due. – Thorarin

+0

Sono d'accordo che dovresti ma non lo devi fare esplicitamente – cgreeno

6

Si potrebbe usare un attributo, come CategoryAttribute:

public enum Position 
{ 
    [Category("Offensive")] 
    Quarterback, 
    [Category("Offensive")] 
    Runningback, 
    [Category("Defensive")] 
    DefensiveEnd, 
    [Category("Defensive")] 
    Linebacker 
}; 
+1

CategoryAttribute è inteso per il raggruppamento di proprietà o eventi nel PropertyGrid e probabilmente non dovrebbe essere abusato per questo tipo di cose. =) –

+1

Perché no? Può essere applicato a qualsiasi cosa, non solo alle proprietà o agli eventi. OK, forse non è * destinato * a quell'uso, ma trasmette piuttosto bene il significato desiderato. IMHO ... –

+0

System.ComponentModel.CategoryAttribute ha già un uso - per me, trasmette un significato completamente diverso da quello che è inteso. –

0

È possibile utilizzare una forma di bit di contrassegno. Ma questo potrebbe portare a un pasticcio. Un modo migliore potrebbe essere quello di creare semplicemente classi personalizzate con i dettagli desiderati e quindi utilizzare un dizionario per cercare ogni tipo di posizione;

public class PlayerPosition { 
    public PlayerPosition (string positionName, bool isDefensive) { 
     this.Name = positionName; 
     this.IsDefensive = isDefensive ; 
    } 
    public string Name { get; private set; } 
    public bool IsDefensive { get; private set; } 
} 

... come enum ...

[Flags] 
public enum Positions { 
    Quarterback = 0x21, 
    Runningback = 0x22, 
    DefensiveEnd = 0x14, 
    Linebacker = 0x18, 

    Defensive = 0x10, 
    Offsensive = 0x20 
} 
+0

dolce ... voto basso senza commenti. che bello ... –

3

forse si può provare ad usare typesefe enum pattern

class Position 
{ 
    public bool Offensive { get; private set; } 
    public bool Defensive { get; private set; } 

    private Position() 
    { 
     Offensive = false; 
     Defensive = false; 
    } 

    public static readonly Position Quarterback = new Position() { Offensive = true }; 
    public static readonly Position Runningback = new Position() { Offensive = true }; 
    public static readonly Position DefensiveEnd = new Position() { Defensive = true }; 
    public static readonly Position Linebacker = new Position() { Defensive = true }; 
} 
+0

% s/privato Possizione/privato Posizione/g –

+0

@iferrorthrownewbrick: ty. fatto. –

1

An sottoutilizzate (ma perfettamente valida) la tecnica è da usare una classe che definisce un insieme di costanti. Come classe, puoi aggiungere proprietà aggiuntive che possono descrivere altri aspetti del valore enumerato. Curiosamente, questo è il modo in cui la maggior parte delle enumerazioni è implementata in Java (che non ha una parola chiave speciale per loro).

Se si segue questo percorso, è generalmente consigliabile rendere la classe sigillata e definire un costruttore privato, in modo che solo la classe stessa possa definire le istanze. Ecco un esempio:

public static class Position 
{ 
    private PlayerPosition (string name, bool isDefensive) { 
     this.Name = name 
     this.IsDefensive = isDefensive ; 
    } 
    // any properties you may need... 
    public string Name { get; private set; } 
    public bool IsDefensive { get; private set; } 
    public bool IsOffensive { get { return !IsDefensive; } } 

    // static instances that act like an enum 
    public static readonly Quarterback = new PlayerPosition("Quarterback", false); 
    public static readonly Runningback = new PlayerPosition("Runningback", false); 
    public static readonly Linebacker = new PlayerPosition("Linebacker", true); 
    // etc... 
} 

Utilizzando tali risultati un enum nella sintassi più elegante e più semplice di attributi:

if(PlayerPosition.Quarterback.IsDefensive) 
{ 
    // ... 
} 
0

è possibile dichiarare le enumerazioni in una classe:

public class Position 
{ 
    public enum Offensive { Quarterback = 1, RunningBack } 
    public enum Defensive { DefensiveEnd = 10, LineBacker } 
} 

Si noti che i valori difensivi iniziano da 10 in modo che i valori non si sovrappongano. Non dichiari perché vuoi farlo, quindi questo potrebbe non soddisfare le tue esigenze.

5
public enum PositionType 
{ 
    Offensive, 
    Defensive, 
} 

public class PositionTypeAttribute : Attribute 
{ 
    public PositionTypeAttribute(PositionType positionType) 
    { 
     PositionType = positionType; 
    } 
    public PositionType PositionType { get; private set; } 
} 

public enum Position 
{ 
    [PositionType(PositionType.Offensive)] 
    Quarterback, 
    [PositionType(PositionType.Offensive)] 
    Runningback, 
    [PositionType(PositionType.Defensive)] 
    DefensiveEnd, 
    [PositionType(PositionType.Defensive)] 
    Linebacker 
}; 

public static class PositionHelper 
{ 
    public static PositionType GetPositionType(this Position position) 
    { 
     var positionTypeAttr = (PositionTypeAttribute)typeof(Position).GetField(Enum.GetName(typeof(Position), position)) 
      .GetCustomAttributes(typeof(PositionTypeAttribute), false)[0]; 
     return positionTypeAttr.PositionType; 

    } 
} 


Position position1 = Position.Runningback; 
Console.WriteLine(position1.GetPositionType()); //print: Offensive 

Position position2 = Position.Linebacker; 
Console.WriteLine(position2.GetPositionType()); //print: Defensive 
+0

+1 L'ultima combinazione di tecniche. Un enum fornisce il parametro a un attributo usato per decorare i valori dei membri di un'altra enumerazione. – AnthonyWJones

+0

Sì :) E il metodo di estensione semplifica notevolmente l'utilizzo. –

+0

Questo aiuta molto, grazie! specialmente perché il tuo codice è pulito e soddisfa tutti i casi in cui abbiamo bisogno di questo tipo di accordo. –

Problemi correlati