2011-10-25 7 views
6

tengo la siguiente enumeración:simple comparar si una enumeración está en una lista de enumeraciones

public enum Materials { Wood, Stone, Earth, Water, Lava, Air } 

Ahora tengo 3materials en el que podía caminar (madera piedra Tierra) y 3 que enviaban aire transitable (lava el agua)

Me gustaría hacer posible comparar si una bandera es una de las tres.

Por el momento, esta es la forma en que lo hago:

Materials myMat = Materials.Earth; 
if (myMat == Materials.Earth || myMat == Materials.Wood || myMat == Materials.Stone) 
{ 
    I can walk on myMat... 
} 

isnt posible la creación de una nueva bandera como Materials.Walkable que incluiría estos tres materiales, así que puede simplemente usar

if (myMat == Materials.Walkable) 

Si esto es posible, ¿cómo puedo hacer eso?

Gracias de antemano;)

Respuesta

12

Se puede crear un método de extensión:

public static bool IsWalkable(this Materials myMat) 
{ 
    return myMat == Materials.Earth || myMat == Materials.Wood || myMat == Materials.Stone; 

    // alternatively: 
    return new[] { Materials.Earth, Materials.Wood, Materials.Stone }.Contains(myMat); 
} 

y utilizarlo como:

Materials myMat = ... 
bool isMyMatWalkable = myMat.IsWalkable(); 

Si lo desea, también se puede utilizar un [Flags] enumeración:

[Flags] 
public enum Materials 
{ 
    None = 0, 
    Wood = 1, 
    Stone = 1 << 1, 
    Earth = 1 << 2, 
    Water = 1 << 3, 
    Lava = 1 << 4, 
    Air = 1 << 5, 
    Walkable = Wood | Earth | Stone 
} 

Y entonces usted puede hacer:

Materials myMat = .. 
bool isMyMatWalkable = (myMat & Materials.Walkable) != Materials.None; 
+1

no sabía que esto era posible en C# –

+0

¿Por qué se definen los valores numéricos para todos los valores de enumeración? Creo que configurarlo solo para 'None' (y' Walkable') funcionaría igual de bien. – svick

+0

Para convertirlos en indicadores de bits, quiere asegurarse de que sean potencias de 2. De lo contrario, sus valores comienzan en 0 y aumentan en 1. – Dismissile

1
System.Enum.GetValues(typeof(Materials)).Contains(myValue) 

reflexión le permite obtener todos los valores de una enumeración, y luego comprueba si está presente. Aunque, no estoy seguro de que pueda resolver la lógica que está tratando de hacer.

Si entiendo su problema de "lógica", probablemente deba convertirlo en clases que también tengan una bandera para indicar si son accesibles. Lo que permite utilizar LINQ para hacer la consulta:

var walkableAreas = AllAreas.Where(area => area.walkable); 
if(walkableAreas.Contains(myArea) { //dostruff // } 

Es pseudo código, pero espero que se obtiene lo que estoy tratando de explicar. Al usar Enums, solo puede tener un valor único, y siempre tendrá que codificar en el enunciado if lo que se puede recorrer y lo que no.

1

se puede tratar de crear atributos personalizados para marcar su material

public enum Materials 
{ 
    [Walkable(true)] 
    Wood, 
    [Walkable(true)] 
    Stone, 
    [Walkable(true)] 
    Earth, 
    [Walkable(false)] 
    Water, 
    [Walkable(false)] 
    Lava, 
    [Walkable(false)] 
    Air 
} 

public class WalkableAttribute : Attribute 
{ 
    public WalkableAttribute(bool value) 
    { 
     IsWalkable = value; 
    } 

    public bool IsWalkable { get; private set; } 
} 

Y a continuación, utilizar la extensión para comprobar si se puede caminar

public static class MaterialsExtemsion 
{ 
    public static bool IsWalkable(this Materials material) 
    { 
     var attribute = material.GetType().GetMember(material.ToString()).First().GetCustomAttributes(typeof(WalkableAttribute), false).FirstOrDefault(); 
     return attribute != null && ((WalkableAttribute) attribute).IsWalkable; 
    } 
} 

y utilizarla

 Materials material1 = Materials.Stone; 
     bool result = material1.IsWalkable(); // return true 

     Materials material2 = Materials.Air; 
     bool result = material2.IsWalkable(); // return false 
1

Tal vez deberías usar una clase con herencia en lugar de simplemente usar un Enum. Esto le permitirá definir todo tipo de propiedades.

public abstract class Material 
{ 
    public abstract bool Walkable(); 
} 


public class Wood : Material 
{ 
    public bool Walkable() 
    { 
     return true; 
    } 
} 

public class Lava: Material 
{ 
    public bool Walkable() 
    { 
     return false; 
    } 
} 
0

¿Consideraría reemplazar la enumeración por una entidad?

public class Material 
{ 
    public string Name {get; set;} 
    public bool IsWalkable {get; set;} 
} 

entonces usted podría hacer la manipulación 'intuitiva' como

Materials.Where(m => m.IsWalkable) 
Cuestiones relacionadas