1

I'm trying get which values of specific enum passed to a method and also what the diffrence between | and & operator when passing enums?

Enum:

enum VectorAxis
{
    X,Y,Z
}

Method:

void SampleMethod(VectorAxis ignoredAxis)
{
// Get witch enums passed
}

Caller:

SampleMethod(VectorAxis.X | VectorAxis.Y);

or

SampleMethod(VectorAxis.X & VectorAxis.Y);
trksyln
  • 136
  • 10
  • 3
    The behavior will depend on the values that are set to the enums (normally they would be set to powers of 2). Please check bitwise operators documentation: https://learn.microsoft.com/es-es/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators – Pablo CG Jun 01 '20 at 10:53
  • 1
    Also maybe have look at the following answer, it explains in great detail how this usually works / is used with enums: https://stackoverflow.com/a/8480/6122062 – bassfader Jun 01 '20 at 10:55
  • 1
    They are logical OR and AND. So your enum is X=0,Y=1,Z=2. So X | Y = (0 | 1), X & Y = (0 & 1). – jdweng Jun 01 '20 at 10:56
  • @bassfader i tried Enum.HasFlag() function and it didn't work. seems like i forget putting [Flags] attribute to my enum thanks. – trksyln Jun 01 '20 at 10:59

3 Answers3

2

First of all, you should apply Flags attribute to your enum. That will indicate that enum can be treated as a set of flags:

[Flags]
enum VectorAxis
{
    // Consider also adding value None = 0 when no axis ignored
    X = 1,
    Y = 2,
    Z = 4
}

Now you can use bitwise operators with enum values:

SampleMethod(VectorAxis.X | VectorAxis.Y); // pass both axis using bitwise OR

How does it work? If you take a look on the binary representation of enum values

X = 001
Y = 010
Z = 100

When you apply bitwise OR operation to X and Y (result has a bit set to 1 if any of values have a bit set to 1 on the same position) you'll get 011. And that's what will be passed to the method. In the method, you can check if the axis were passed using bitwise AND

public void SampleMethod(VectorAxis ignoredAxis)
{
     if ((ignoredAxis & VectorAxis.X) == VectorAxis.X) // check using bitwise AND
        // X is ignored
}

The result of bitwise AND (you have 1 only when both values have a bit set to 1 on same position) of passed value 011 and value of X 001 gives you back value of X only when the corresponding bit is enabled in passed value.

011 & 001 = 001 // X is ignored
011 & 010 = 010 // Y is ignored
011 & 100 = 000 // Z is not ignored

Also instead of checking value manually, you can use Enum.HasFlag method which does the same

if (ignoredAxis.HasFlag(VectorAxis.X)) 
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
2

This is normally done to unify different conditions that are represented by enums. Then, when you use &, you expect that both are satisfied. When using |, one of them is enough.

Given these are bitwise operators, normally values set to the enums are powers of 2, and then you can combine two or more values using the sum of all of them. Check this example:

public enum Values {
    A = 1,
    B = 2,
    C = 4,
    D = 8,
    B_And_D = 10, // Both B and D applies
    A_B_C_And_D = 15, // All apply
}

public static void Main()
{
    var input = Values.B & Values.B_And_D;
    Console.WriteLine(input); // returns B

    var input2 = Values.B | Values.B_And_D;
    Console.WriteLine(input2); // returns B_And_D

    var input3 = Values.B_And_D & Values.A_B_C_And_D;
    Console.WriteLine(input3); // returns B_And_D

    var input4 = Values.B_And_D | Values.A_B_C_And_D;
    Console.WriteLine(input4); // returns A_B_C_And_D
}

Normally you would apply this logic using the Flags attribute, which simplifies much more the logic to combine the conditions (you don't need to add them manually): https://learn.microsoft.com/en/dotnet/api/system.flagsattribute

Pablo CG
  • 818
  • 6
  • 18
1

Enums work just like an integer, every enum value has a numerical value. If you don't set that value to anything and leave it default (like you did with VectorAxis) they will have values from 0 up to the limit of the underlying type (usually int, unless you change it). This means performing bitwise operations on them is the same as bitwise operations on integers.

If you don't know how bitwise operations work you can read about them here.

If you want to be able to use them as flags you have to set the values to powers of 2. Let's do that:

enum VectorAxis
{
    X = 1,
    Y = 2,
    Z = 4,
}

And to make printing easier let's add the flags attribute.

[Flags]
enum VectorAxis

Now if you print VectorAxis.X | VectorAxis.Y to console you get X, Y. If you want to know if the passed value has the Z flag, you can use the bitwise and:

(ignoredAxis & VectorAxis.Z) != 0

If you call the SampleMethod with VectorAxis.X | VectorAxis.Y the result is false. but if you change the parameter to VectorAxis.X | VectorAxis.Z the result will be true. You can use this to check every axis.

Raphtaliyah
  • 207
  • 1
  • 6