Click here to Skip to main content
15,883,883 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

 
SuggestionFinally Implemented with Visual Studio 15 preview Pin
Banketeshvar Narayan2-Apr-16 20:59
professionalBanketeshvar Narayan2-Apr-16 20:59 
GeneralRe: Finally Implemented with Visual Studio 15 preview Pin
Sascha Lefèvre10-Apr-16 14:10
professionalSascha Lefèvre10-Apr-16 14:10 
Generalthoughts about 29-bit binary literal Pin
jediYL28-Mar-16 17:38
professionaljediYL28-Mar-16 17:38 
GeneralRe: thoughts about 29-bit binary literal Pin
Sascha Lefèvre28-Mar-16 23:16
professionalSascha Lefèvre28-Mar-16 23:16 
QuestionEnhanced C# Pin
Qwertie28-Mar-16 16:54
Qwertie28-Mar-16 16:54 
AnswerRe: Enhanced C# Pin
Sascha Lefèvre28-Mar-16 23:26
professionalSascha Lefèvre28-Mar-16 23:26 
QuestionWhy not a new value type? Pin
Rafael Nicoletti22-Mar-16 15:32
Rafael Nicoletti22-Mar-16 15:32 
Questionsome comments Pin
sx200825-Feb-16 9:25
sx200825-Feb-16 9:25 
AnswerRe: some comments Pin
Sascha Lefèvre25-Feb-16 10:05
professionalSascha Lefèvre25-Feb-16 10:05 
QuestionHighly inefficient Pin
irneb24-Feb-16 3:52
irneb24-Feb-16 3:52 
AnswerRe: Highly inefficient Pin
Sascha Lefèvre24-Feb-16 4:17
professionalSascha Lefèvre24-Feb-16 4:17 
AnswerRe: Highly inefficient Pin
webmaster44224-Feb-16 23:49
webmaster44224-Feb-16 23:49 
A compiler would result in a pre processor, which would be great for this specific purpose, but it would be a very bad idea for code maintainability. InteliSense would throw errors all the time. Smile | :)
GeneralRe: Highly inefficient Pin
irneb25-Feb-16 0:53
irneb25-Feb-16 0:53 
GeneralRe: Highly inefficient Pin
Qwertie28-Mar-16 17:03
Qwertie28-Mar-16 17:03 
SuggestionSlight improvement Pin
Richard Deeming22-Feb-16 9:19
mveRichard Deeming22-Feb-16 9:19 
GeneralRe: Slight improvement Pin
Sascha Lefèvre22-Feb-16 12:06
professionalSascha Lefèvre22-Feb-16 12:06 
GeneralRe: Slight improvement Pin
Richard Deeming23-Feb-16 1:40
mveRichard Deeming23-Feb-16 1:40 
GeneralRe: Slight improvement Pin
Sascha Lefèvre23-Feb-16 3:27
professionalSascha Lefèvre23-Feb-16 3:27 
GeneralRe: Slight improvement Pin
Richard Deeming23-Feb-16 3:31
mveRichard Deeming23-Feb-16 3:31 
GeneralRe: Slight improvement Pin
Sascha Lefèvre23-Feb-16 3:44
professionalSascha Lefèvre23-Feb-16 3:44 
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 

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.