Search code examples
c#c++bit-manipulationoperator-keyword

C# performing bitwise operation with & from C++


Anyway here's my problem I have been modifying a whole C++ program to work in C# and I am pretty much done, I have this If statement in the C++ program.

if(info[i].location & 0x8 || 
             info[i].location & 0x100|| 
                     info[i].location & 0x200)
{
    //do work
}
else
{
    return
}

And of course when I do this in C# it gives me a "Operator '||' cannot be applied to operands of type 'int' and 'int'" error.

Any clue on what my problem is, Im guessing that C# has got a way of doing this as I am fairly unfamiliar with these old C operators.


Solution

  • Why it fails

    Fundamentally it's the same difference as this:

    if (someInteger) // C or C++
    

    vs

    if (someInteger != 0) // C#
    

    Basically C# is a lot stricter when it comes to logical operators and conditions - it forces you to have use something which is either bool or convertible to bool.

    As an aside, that's also why in C# this isn't just a warning, but a full-blown error:

    int x = ...;
    if (x = 10) // Whoops - meant to be == but it's actually an assignment
    

    If you see comparisons this way round:

    if (10 == x)
    

    That's usually developers trying to avoid typos like the above - but it's not needed in C# unless you're really comparing against constant bool values.

    Fixing the problem

    I suspect you just need:

    if (((info[i].location & 0x8) != 0)) ||
        ((info[i].location & 0x100) != 0)) ||
        ((info[i].location & 0x200) != 0)))
    

    It's possible that you don't need all of those brackets... but another alternative is just to use one test:

    if ((info[i].location & 0x308) != 0)
    

    After all, you're just testing whether any of those three bits are set...

    You should also consider using a flags-based enum:

    [Flags]
    public enum LocationTypes
    {
        Foo = 1 << 3; // The original 0x8
        Bar = 1 << 8; // The original 0x100
        Baz = 1 << 9; // The original 0x200
    }
    

    Then you could use:

    LocationTypes mask = LocationTypes.Foo | LocationTypes.Bar | LocationTypes.Baz;
    if ((info[i].location) & mask != 0)
    

    Or using Unconstrained Melody:

    LocationTypes mask = LocationTypes.Foo | LocationTypes.Bar | LocationTypes.Baz;
    if (info[i].location.HasAny(mask))