Simulating Binary Literals in C#



Introduction

Although C# supports hexadecimal literals (such as 0x30, 0x45 etc), it doesn't support octal (base 8) or binary (base 2) literals.

The argument has been that they are unnecessary because most people who use bit arithmetic in their work, already know the bit patterns for each of the 16 hex digits by heart. Also octal is not used much nowadays though binary, of course, still is.

I think this argument may credit developers with better memories than they actually have so is there any way we can simulate binary literals in C#?


What support for binary do we have already?

The only support I'm aware of is methods in the Convert class which can convert binary strings to various types of integer. For example:

int x = Convert.ToInt32("1111", 2); // x == 15

However, this method uses strings. Could we use integers instead so that we can easily do bit and normal arithmetic with binary numbers?

A possible solution

Some languages such as F# support binary literals by preceding them with '0b'. For example 0b1111 denotes the binary number 15.

Although we can't do this in C#, I've devised a struct called Bin which enables us to use notation such as (b)1111 instead. This works by converting the binary integer explicitly to Bin and then converting it implicitly back to a normal integer!

The prefix 'b' is just an alias for the Bin struct.

I decided to limit the range of Bin to binary numbers in the range 0 to 1111111. If you use more than 8 digits (i.e. the maximum size for a byte) then binary quickly becomes unreadable

The following example which includes basic code for the Bin struct should make all this clear:

using System;
using b = Bin; // alias for Bin struct
 
class Test
{
    static void Main()
    {
        int x = 0xffff;
        int y = (b)1111;
        int z = x & y;
        Console.WriteLine(z);
        z = x | y;
        Console.WriteLine(z);
        z = (b)11110000 + (b)00001111;
        Console.WriteLine(z);
        Console.WriteLine("{0}", (b)10111);
        byte by = (b)101;
        Console.WriteLine(by);
        Console.ReadKey();
    }
}

public struct Bin
{
    int num;
 
    private Bin(int i)
    {
        num = i;
    }
 
    public static implicit operator int(Bin bin)
    {
        return bin.num;
    }

    public static implicit operator byte(Bin bin)
    {
        return (byte)bin.num;
    }

    public static explicit operator Bin(int i)
    {
        if (i < 0 || i > 11111111) throw new ArgumentException("Argument must be between 0 and 11111111");
        if (i.ToString().IndexOfAny("23456789".ToCharArray()) > -1) throw new ArgumentException("Binary number can only contain 0 or 1");
        int dec = 0;
        int pow2 = 1;
        do
        {
            if ((i & 1) == 1) dec |= pow2;
            i /= 10;
            pow2 <<= 1;
        }
        while (i > 0);
        return new Bin(dec);
    }

    public override string ToString()
    {
        return "0b" + Convert.ToString(num, 2);
    }

}

Test Results

When you run this code the results should be:
15
65535
255
0b10111
5