7

I have the following enum:

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

Now I have 3materials on which i could walk (wood stone earth) and 3 which arent walkable (water lava air)

I would like to make it possible to compare if a flag is one of the three.

At the moment, this is how I do it:

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

isnt it possible to create a new flag like Materials.Walkable which would include these three materials so I can just use

if ( myMat == Materials.Walkable )

If this is possible, how can I do that?

Thanks in advance ;)

5 Answers 5

14

You could create an extension method:

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

And use it as:

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

If you like, you could also use a [Flags] enum:

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

And then you can do:

Materials myMat = ..
bool isMyMatWalkable = (myMat & Materials.Walkable) != Materials.None;
Sign up to request clarification or add additional context in comments.

12 Comments

didn't knew this was possible in C#
Why do you define the numeric values for all the enum values? I think setting it just for None (and Walkable) would work just as well.
In order to make them bit flags you want to make sure they are powers of 2. Otherwise your values start at 0 and increase by 1.
I am doing it as follows now:if ((Materials.Water & Materials.Walkable) != Materials.None) Console.WriteLine("wrong"); if ((Materials.Wood & Materials.Walkable) != Materials.None) Console.WriteLine("true"); if ((Materials.Water & Materials.UnWalkable) != Materials.None) Console.WriteLine("true"); if ((Materials.Wood & Materials.UnWalkable) != Materials.None) Console.WriteLine("wrong"); it is working as desired, but isn't there a "simpler" solution without creating a method for this
@svick: Then the bitwise combinations wouldn't work correctly. We are relying on the fact that each 'non-complex' enum value is associated with a specific bit being set.
|
1
System.Enum.GetValues(typeof(Materials)).Contains(myValue)

Reflection allows you to get all the values for an Enum, and then check if it's present. Although, i'm not sure you can solve the logic you're trying to do.

If I understand your "logic" problem, you'll probably have to turn it into classes that also have a flag to signal whether they're walkable. Allowing you to use linq to make the query:

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

It's pseudo code, but I hope you get what I'm trying to explain. Using Enums you can only have a single value, and you'll always have to hardcode in the if-statement what's walkable and what isn't.

Comments

1

Perhaps you should use a class with inheritance instead of just using an Enum. This will allow you to define all kinds of properties.

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

Comments

1

Would you consider replacing the enum with an Entity?

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

Then you could do 'intuitive' manipulation such as

Materials.Where(m => m.IsWalkable)

Comments

1

You can try to create custom Attribute to mark your 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; }
}

And then use extension to check if it is Walkable

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

then use it

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

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.