-2

In order to check hihest bit is on I use code:

byte data = 0x88 ;
bool is_on= ((data & 0x80) == 0x80);

How to do this in more elegant and C# way ?

vico
  • 17,051
  • 45
  • 159
  • 315
  • 1
    I think you probably meant `((data & 0x80) == 0x80)`. Since you're just testing a single bit, and not multiple bits, you can simplify to `(data & 0x80) > 0` if you want. – canton7 Mar 16 '21 at 17:09
  • 2
    In C# you'd normally use flag enums for this, rather than bitfields. If you must work with bitfields, using low-level bit operations is probably the way to go: you can use `BitArray` if you want, but it's a lot of overhead – canton7 Mar 16 '21 at 17:11
  • 2
    Elegance is overrrated. Many people think clarity is more important. This code is pretty clear as it is. In C++ (and I think C# has it to) I like implicit conversion to bool, e.g., `bool is_on = data & 0x80;`. But I find in code reviews that my peers think that's too ... elegant. Or something. They prefer the clarity of `bool is_on = (data & 0x80) != 0;`. So I've learned from them. – davidbak Mar 16 '21 at 17:15
  • 1
    "*and I think C# has it to*" -- nope it does not, for the same reason that many coding standards forbid implicit conversions to bool, and many other languages also forbid, or at least severely limit, it – canton7 Mar 16 '21 at 17:17
  • Also look into [`System.Collections.Specialized.BitVector32`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.specialized.bitvector32?view=net-5.0) – JAlex Mar 16 '21 at 18:23

3 Answers3

1
public static bool Get(byte b, int position)
{
    if (position > 7)
        throw new ArgumentException();

    return ((b & (byte)(1 << position)) != 0);
}
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
0

Since you're checking a bit, the only thing I might do is write out the literal so you can see the individual bits, like this:

int mask = 0b1000_0000;

byte data = 0x88 ;
bool is_on= ((data & mask) == mask);

I might further abstract this as a method:

public static bool MatchesMask(this int data, int mask)
{
    return (data&mask)==mask;
}

So I could call it like this:

int mask = 0b1000_0000;

byte data = 0x88 ;
bool is_on = data.MatchesMask(mask);
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
0

If you are dealing with bit setting and getting consider some auxiliary classes to help you. Look at the Flag structure below

Usage

You initialize a Flag with a mask Flag flag = 0x20, or set a specific bit Flag flag = Flag.Bit(5).

You poll a bit with flag.Get(value) and you set a bit with value = flag.Set(value); to set to 1, and value = flag.Set(value, false); to set it 0.

Test Output

10110011 & 00100000 = True
10010011 & 00100000 = False

Code

public struct Flag
{
    readonly byte mask;

    public Flag(byte mask)
    {
        this.mask=mask;
    }

    public byte Mask => this.mask;

    public static Flag Bit(int position)
        => new Flag((byte)(1<<position));
    public static implicit operator byte(Flag bit) => bit.mask;
    public static implicit operator Flag(byte mask) => new Flag(mask);

    public bool Get(byte value) => (value & mask)!=0;
    public byte Set(byte value, bool bit = true)
    {
        if (bit)
        {
            return (byte)(value | mask);
        }
        else
        {
            return (byte)(value & ~mask);
        }
    }
}

static class Program
{
    public static string Bin(this byte data)
        => Convert.ToString(data, 2).PadLeft(8, '0');

    static void Main(string[] args)
    {
        byte value = 0xB3;

        Flag flag = 0x20;
        // or alernativly
        // var flag = Flag.Bit(6); // mask = 0b0010000 
        Console.WriteLine($"{Bin(value)} & {Bin(flag.Mask)} = {flag.Get(value)}");

        // not set the bit to 0
        value = flag.Set(value, false);
        Console.WriteLine($"{Bin(value)} & {Bin(flag.Mask)} = {flag.Get(value)}");
    }
}

References

JAlex
  • 1,486
  • 8
  • 19