2010-01-21 13 views
13

Dada la siguiente enumeración:C#: ¿Hay alguna manera de clasificar las enumeraciones?

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

¿Es posible clasificar las constantes con nombre, de modo que pude marcar 'quarterback' y 'Runningback' como posiciones ofensivas y 'defensive end' y 'linebacker' como posiciones defensivas?

+0

Es una pregunta interesante, incluso si se está tratando enumeraciones de abuso, tengo una pregunta a cambio ... ¿por qué no usar un jugador de clase con propiedades tanto para la posición y si están en el equipo defensivo u ofensivo? – Lazarus

Respuesta

7

Por qué no beso:

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

Es posible que desee utilizar un nombre de enumeración que no sea Type, que tenga System.Type alrededor y todo. La desambiguación cada vez que la usas puede ser realmente molesta. :) – GeReV

21

Puede utilizar atributos:

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

Y a continuación, comprobar si hay IsDefined en una adecuada FieldInfo. Sintaxis no es muy bonita, pero se puede lanzar en un par de métodos de extensión para hacer las cosas más manageble:

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

+1 He usado este método en una situación similar, pero he descubierto que llegar a los atributos es bastante doloroso en el caso de las enumeraciones –

+0

No es necesariamente doloroso ... puede crear un método de extensión para recuperar el atributo , y solo reutilízalo cada vez que lo necesites –

+0

Ya dado mi +1, incluso si encuentro el reflejo a veces es un método bastante costoso para tal locura. =) –

5

usted podría utilizar 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

¿Desea aclarar sus ideas sobre cómo Flags podría resolver la pregunta de askers? –

+2

Al usar '[Flags]', también debe especificar constantes de enumeración en potencias de dos. – Thorarin

+0

Acepto que debe hacerlo, pero no tiene que hacerlo explícitamente – cgreeno

6

Se podría utilizar un atributo, como CategoryAttribute:

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

El atributo de categoría está destinado a agrupar propiedades o eventos en PropertyGrid y probablemente no se debe abusar de este tipo de cosas. =) –

+1

¿Por qué no? Se puede aplicar a cualquier cosa, no solo a propiedades o eventos. OK, quizás no es * intencionado * para ese uso, pero transmite el significado deseado bastante bien en mi humilde opinión ... –

+0

System.ComponentModel.CategoryAttribute ya tiene un uso - para mí, transmite un significado completamente diferente de lo que se pretende. –

0

Puede usar alguna forma de bits de marca. Pero eso podría llevar a un desastre. Una mejor manera puede ser simplemente crear clases personalizadas con los detalles que desee y luego usar un diccionario para buscar cada tipo de posición;

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

... como enumeración ...

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

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

dulce ... abajo vote sin comentarios. qué bueno ... –

3

Tal vez usted puede tratar de utilizar 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/privado Posición/posición privada/g –

+0

@iferrorthrownewbrick: ty. hecho. –

1

Un poco utilizado (pero perfectamente válida) la técnica es usar una clase que define un conjunto de constantes. Como clase, puede agregar propiedades adicionales que pueden describir otros aspectos del valor enumerado. Curiosamente, esta es la forma en que la mayoría de las enumeraciones se implementan en Java (que no tiene una palabra clave especial para ellas).

Si sigue esta ruta, generalmente es una buena idea sellar la clase y definir un constructor privado, de modo que solo la clase misma pueda definir instancias. He aquí un ejemplo:

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

Utilizando los resultados de este tipo de una enumeración en la sintaxis más elegante y más simple que los atributos:

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

puede declarar las enumeraciones en una clase:

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

Tenga en cuenta que los valores defensivos comienzan en 10 para que los valores no se superpongan. No indicas por qué quieres hacer esto, por lo que es posible que esto no satisfaga tus necesidades.

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 La mejor combinación de técnicas. Una enumeración proporciona el parámetro a un atributo utilizado para decorar los valores de miembro de otra enumeración. – AnthonyWJones

+0

Sí) :) Y el método de extensión simplifica enormemente el uso. –

+0

Este ayuda mucho, ¡Gracias! especialmente porque su código está limpio y satisface todos los casos en que necesitamos este tipo de arreglo. –

Cuestiones relacionadas