MonkeyCoder
MonkeyCoder

Reputation: 2620

Enum combinations and bitwise operators

I have the following enums defined in my code:

[Flags]
public enum Symbol
{
    A,
    B,
}

public enum Production
{
    AA = Symbol.A | Symbol.A,
    AB = Symbol.A | Symbol.B,
    BA = Symbol.B | Symbol.A, // <- this will obviously not work
}

I was planning to make use of enums as they eventually would prevent unwanted Symbols to be used for Productions. The problem is that the following code does not produce the output that I'm after:

Productions product1 = (Productions) (Symbol.A | Symbol.A); // Production.AA
Productions product2 = (Productions) (Symbol.A | Symbol.B); // Production.AB
Productions product3 = (Productions) (Symbol.B | Symbol.A); // Production.AB (and not Production.BA as I would like)

I completely understand why this is happening, but was wondering if there is a combination of bitwise operators that I could use to make it work as I originally intended?

Or maybe in general I'm trying to use enums in a incorrect way, therefore should switch to chars or even custom structs?

Upvotes: 0

Views: 1473

Answers (3)

Guffa
Guffa

Reputation: 700790

As you want to keep information about both the value and posititon, you would need to use different enum value for different values at different positions:

[Flags]
public enum Symbol {
  FirstA = 1,
  FirstB = 2,
  SecondA = 4,
  SecondB = 8
}

public enum Production {
  AA = Symbol.FirstA | Symbol.SecondA,
  AB = Symbol.FirstA | Symbol.SecondB,
  BA = Symbol.FirstB | Symbol.SecondA
}

Upvotes: 0

Austin Henley
Austin Henley

Reputation: 4633

You are trying to perform pattern matching. This is not what enums are for. Languages such as F# have a great mechanism built-in to do this, for example:

match expression with 
| pattern_1 -> expression_1 
| pattern_2 -> expression_2 
| pattern_n -> expression_n

But C# does not have this [yet]. There is a great project to add a library to C# to give it this functionality called Functional C#. I think that library is your best bet.

Upvotes: 0

Nikola Davidovic
Nikola Davidovic

Reputation: 8666

Well, because you need to take care of the order of A and B than you should use some operation that is not commutative. I would better suggest the approach where each position should have the assigned weight and you can have simple addition of symbols with weights. Since Enums are ints you can assign to each position a weight of 10^i where i is the zero-based index of the position looking from right to left. Even then you can have calculations for even more Symbols. This is like with classic Arabic numbers but with your symbols instead of regular digits. The code can be like this:

    [Flags]
    public enum Symbol
    {
        A,
        B,
    }

    public enum Production
    {
        AA = Symbol.A *10 + Symbol.A, //0
        AB = Symbol.A *10 + Symbol.B, //1
        BA = Symbol.B *10 + Symbol.A, //10
    }

Upvotes: 2

Related Questions