Click here to Skip to main content
15,885,309 members
Articles / Programming Languages / C#
Tip/Trick

C# Binary Literal Helper Class

Rate me:
Please Sign up or sign in to vote.
4.69/5 (13 votes)
22 Mar 2016CPOL2 min read 51.2K   11   28
C# doesn't allow for binary literals (e.g. int bits = 0b00010101). With the helper class presented here, you can do something like that, as close as possible.

Introduction

When you're dealing with bitwise operations, the possibility to initialize variables or constants with binary literals would be helpful so that you could read the value the way it will be interpreted by your code.

Background

Initially, it was planned for C# 6.0 to introduce binary literals. Unfortunately, this feature wasn't implemented and is now scheduled for C# 7.0.

So I wrote a small helper class which allows you to do something like that, as close as possible.

Using the Code

The following class allows you to write a binary literal in the form of a string literal which will be converted into an integer of choice:

C#
public static class BinaryLiteral
{
    public static byte BinaryLiteralToByte(this string str)
    {
        return ToByte(str);
    }

    public static short BinaryLiteralToInt16(this string str)
    {
        return ToInt16(str);
    }

    public static int BinaryLiteralToInt32(this string str)
    {
        return ToInt32(str);
    }

    public static long BinaryLiteralToInt64(this string str)
    {
        return ToInt64(str);
    }

    public static byte ToByte(string str)
    {
        return (byte)ToInt64(str, sizeof(byte));
    }

    public static short ToInt16(string str)
    {
        return (short)ToInt64(str, sizeof(short));
    }

    public static int ToInt32(string str)
    {
        return (int)ToInt64(str, sizeof(int));
    }

    public static long ToInt64(string str)
    {
        return ToInt64(str, sizeof(long));
    }

    private static long ToInt64(string str, int sizeInBytes)
    {
        int sizeInBits = sizeInBytes * 8;
        int bitIndex = 0;
        long result = 0;

        for (int i = str.Length - 1; i >= 0; i--)
        {
            char c = str[i];

            if (c != ' ')
            {
                if (bitIndex == sizeInBits)
                {
                    throw new OverflowException("binary literal too long: " + str);
                }

                if (c == '1')
                {
                    result |= 1L << bitIndex;
                }
                else if (c != '0')
                {
                    throw new InvalidCastException(String.Format("invalid character '{0}' in binary literal: {1}", c, str));
                }

                bitIndex++;
            }
        }

        return result;
    }
}

Then, you can use it like this:

C#
static byte myByteBitMask = BinaryLiteral.ToByte("                        0110 1100");
static short myInt16BitMask = BinaryLiteral.ToInt16("           1000 0000 0110 1100");
static int myInt32BitMask = BinaryLiteral.ToInt32("   0101 1111 1000 0000 0110 1100");
static long myInt64BitMask = BinaryLiteral.ToInt64("  0101 1111 1000 0000 0110 1100");

Or, if you prefer extension methods, like this:

C#
static byte myByteBitMask = "                       0110 1100".BinaryLiteralToByte();
static short myInt16BitMask = "           1000 0000 0110 1100".BinaryLiteralToInt16();
static int myInt32BitMask = "   0101 1111 1000 0000 0110 1100".BinaryLiteralToInt32();
static long myInt64BitMask = "  0101 1111 1000 0000 0110 1100".BinaryLiteralToInt64();

Separation of "bit-blocks" with blanks is optional and can be used at any position.

If you leave out high bits (in the above example, I skipped the 8 high bits of the Int32 and the 40 high bits of the Int64), they're treated as zeroes.

An unavoidable limitation of this solution is that you can't use it to initialize a constant identifier. So you would have to use readonly variables instead of const identifiers.

As the binary literal is a string constant, the variables you initialize with these methods normally should be static to avoid repeated conversion.

Points of Interest

If you want to use underscores instead of blanks to separate "bit-blocks", just replace if (c != ' ') with if (c != '_') - or, to allow both: if (c != ' ' && c != '_') .

You could achieve the same thing as this class by using only .NET-standard methods:

C#
static int myBitMask = Convert.ToInt32("1000 0000 0110 1100".Replace(" ", ""), 2);

But it's more to type and it's less descriptive, which, I believe, is an important aspect of code.

If you favor switch-statements over if-statements take a look at Richard Deeming's proposed alternative way of writing the conversion code in his comment below.

History

  • 22nd Mar, 2016: Added extension methods
  • 24th Feb, 2016: Added hint about "static usage" and some other small improvements
  • 23rd Feb, 2016: Some small improvements on readibility, conciseness and performance
  • 22nd Feb, 2016: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
1985: "Hello world" on a Colour Genie
1989: Basic Balls of Mud on an Amiga 500
1994: C++ Big Balls of Mud on a PC
2005: C# Smaller Balls of Mud

Avatar image © dpa (licensed).



Comments and Discussions

 
SuggestionAlternative Approach... Pin
Andrew Rissing22-Feb-16 6:51
Andrew Rissing22-Feb-16 6:51 
GeneralRe: Alternative Approach... Pin
Sascha Lefèvre22-Feb-16 7:12
professionalSascha Lefèvre22-Feb-16 7:12 
GeneralRe: Alternative Approach... Pin
Andrew Rissing22-Feb-16 7:26
Andrew Rissing22-Feb-16 7:26 
GeneralRe: Alternative Approach... Pin
Sascha Lefèvre22-Feb-16 8:25
professionalSascha Lefèvre22-Feb-16 8:25 
GeneralRe: Alternative Approach... Pin
Andrew Rissing22-Feb-16 8:39
Andrew Rissing22-Feb-16 8:39 
GeneralRe: Alternative Approach... Pin
Sascha Lefèvre22-Feb-16 9:19
professionalSascha Lefèvre22-Feb-16 9:19 
SuggestionRe: Alternative Approach... Pin
Richard Deeming22-Feb-16 9:09
mveRichard Deeming22-Feb-16 9:09 
GeneralRe: Alternative Approach... Pin
Andrew Rissing22-Feb-16 10:20
Andrew Rissing22-Feb-16 10:20 
What so ever do you mean? Cool | :cool:

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.