230

Is there a way to write binary literals in C#, like prefixing hexadecimal with 0x? 0b doesn't work.

If not, what is an easy way to do it? Some kind of string conversion?

toxvaerd
  • 3,622
  • 3
  • 24
  • 29
  • 2
    Use constants and give them proper names, then the fact that you have to write them out in decimal shouldn't matter. Personally I'd want to read `if (a == MaskForModemIOEnabled)` rather than `if (a == 0b100101)` – Lasse V. Karlsen Jul 29 '10 at 11:44
  • 2
    Another note: If you found this post because you want a bit field, please consider the flags-attribute: http://msdn.microsoft.com/en-us/library/cc138362.aspx#sectionToggle0 – toxvaerd Nov 09 '10 at 10:29
  • 20
    Both very good advice, except when *defining* said bitfields, where these named constant definitions can be easier to read and write with a binary literal. [Flags]enum Quantity { None=0, One=1, Some=0b10, Most=0b100, All=0b111 } – brianary Dec 28 '10 at 23:43

12 Answers12

229

Update

C# 7.0 now has binary literals, which is awesome.

[Flags]
enum Days
{
    None = 0,
    Sunday    = 0b0000001,
    Monday    = 0b0000010,   // 2
    Tuesday   = 0b0000100,   // 4
    Wednesday = 0b0001000,   // 8
    Thursday  = 0b0010000,   // 16
    Friday    = 0b0100000,   // etc.
    Saturday  = 0b1000000,
    Weekend = Saturday | Sunday,
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}

Original Post

Since the topic seems to have turned to declaring bit-based flag values in enums, I thought it would be worth pointing out a handy trick for this sort of thing. The left-shift operator (<<) will allow you to push a bit to a specific binary position. Combine that with the ability to declare enum values in terms of other values in the same class, and you have a very easy-to-read declarative syntax for bit flag enums.

[Flags]
enum Days
{
    None        = 0,
    Sunday      = 1,
    Monday      = 1 << 1,   // 2
    Tuesday     = 1 << 2,   // 4
    Wednesday   = 1 << 3,   // 8
    Thursday    = 1 << 4,   // 16
    Friday      = 1 << 5,   // etc.
    Saturday    = 1 << 6,
    Weekend     = Saturday | Sunday,
    Weekdays    = Monday | Tuesday | Wednesday | Thursday | Friday
}
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • 27
    @ColeJohnson: Many developers prefer that. I'm not as good at converting hex in my head as some developers are, and sometimes it's best to cater to the lowest common denominator. – StriplingWarrior Jun 22 '12 at 02:50
  • 2
    I think this is the most effective way since enums are built as constants. With the optional [Flags] attribute they can be used in bitwise operations (not directly related to the question, but particularly useful when describing binary literals). Another interesting possibility is to force the enum type as a built-in type (in this example, add ' : byte' after 'Days'); see built-in types in http://bit.ly/MKv42E – caligari Jul 07 '12 at 18:37
  • That is actually very easy to read, though declaring a 0 flag on a Enum is fairly bad practice – MikeT Jun 10 '15 at 09:11
  • 6
    @MikeT: Can you elaborate (or provide a link that elaborates) on that last thought? I often declare enums that start with "1" because I want to be able to [detect and fail-fast](http://stackoverflow.com/a/6413841/120955) when a value was simply never initialized. But there are some situations where a default value actually makes sense, and I'd think there wouldn't be anything wrong with adding a name for that value. – StriplingWarrior Jun 10 '15 at 15:24
  • Its because Flags are designed to be used in bitwise operators and 0 when &'ed with 0 returns false even though they are Equal, because this changes the behaviour of any enum based comparison the 0 value shouldn't be enumerated. – MikeT Jun 11 '15 at 09:02
  • Humm just trying to find corroboration for that and i'm finding more thats for the 0 flag than against it. i do recall that i used to think the 0 flag was the right way until a very long and complex conversation with someone convinced me that i was wrong. – MikeT Jun 11 '15 at 09:17
  • @MikeT: Actually when using flags, the convention is to `|` them (bitwise or) when specifying configuration or behavior. When reading them, it is convention to do `if ((settings & flag) == flag) { ... }` (that's how .NET's enum.HasFlag is implemented), in which case a bit flag of 0 would be fine if it means default behavior that you don't explicitly check for. – Roy Tinker Nov 04 '15 at 18:03
  • @RoyTinker: If you do that sort of comparison then everything comes out equal to the default value, though. I can see the argument that `Sunday` should not be considered to "have" the `None` flag. But there are equally valid arguments for saying that a bit set with no days is just as valid as one with multiple days, so this is probably one of those cases where you just have to accept the fact that there will be some custom code when you're trying to deal with the concept of "no flags". – StriplingWarrior Nov 04 '15 at 18:21
  • @StriplingWarrior: Yes, every possible flags value would come out equal to zero if `&`'ed with zero.. That's why I said a bit flag of `0` should mean default behavior that you _don't_ check for. – Roy Tinker Nov 04 '15 at 19:03
  • This format is also very useful if you started out with a normal Enum (1, 2, ..) and want to add the [Flags] attribute later. You can fix it with a column-mode edit or a replace action. – GreatBittern Nov 23 '16 at 07:16
  • 4
    @MikeT From [ca1008](https://learn.microsoft.com/en-us/visualstudio/code-quality/ca1008-enums-should-have-zero-value?view=vs-2017): **"If an enumeration that has the FlagsAttribute applied defines a zero-valued member, its name should be 'None' to indicate that no values have been set in the enumeration."** So it's perfectly valid to add it to serve as default value, _if_ it's called "None". Overall it just seems cleaner to me if the value in a default-initialised field actually has a name to show. – Nyerguds Jan 09 '19 at 11:06
  • With C# 7 binary literals I have a question. Is there a difference between the following 0b01 0b001 0b0001 – John Demetriou May 17 '22 at 12:37
  • 1
    @JohnDemetriou. There is no difference between those in the compiled code, for the same reason `01` is no different from `1`. But including those zeros can help developers to visualize where the ones and zeros are. – StriplingWarrior May 17 '22 at 16:04
181

C# 7.0 supports binary literals (and optional digit separators via underscore characters).

An example:

int myValue = 0b0010_0110_0000_0011;

You can also find more information on the Roslyn GitHub page.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
BTownTKD
  • 7,911
  • 2
  • 31
  • 47
  • 1
    It helps to remember that C#'s Binary Literals are big-endian, but on x86 integers are little-endian, so `Int16 = 0b0010_0110_0000_0011` will be stored as `{ 0b0000_0011, 0b0010_0110 }` - confusing. – Dai May 20 '19 at 13:36
  • 2
    @Dai that’s no different than hex literals. In other words, all constants are big endian, but stored little endian on Intel/AMD and most ARMs. `0xDEADBEEF` will be stored as `0xEF 0xBE 0xAD 0xDE` – Cole Tobin Sep 02 '19 at 18:28
  • This is because *human language* (at least western?) is big endian and number literals in source code match that. Thankfully. – Oskar Berggren May 27 '23 at 09:44
118

Only integer and hex directly, I'm afraid (ECMA 334v4):

9.4.4.2 Integer literals Integer literals are used to write values of types int, uint, long, and ulong. Integer literals have two possible forms: decimal and hexadecimal.

To parse, you can use:

int i = Convert.ToInt32("01101101", 2);
El Ronnoco
  • 11,753
  • 5
  • 38
  • 65
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
27

Adding to @StriplingWarrior's answer about bit flags in enums, there's an easy convention you can use in hexadecimal for counting upwards through the bit shifts. Use the sequence 1-2-4-8, move one column to the left, and repeat.

[Flags]
enum Scenery
{
  Trees   = 0x001, // 000000000001
  Grass   = 0x002, // 000000000010
  Flowers = 0x004, // 000000000100
  Cactus  = 0x008, // 000000001000
  Birds   = 0x010, // 000000010000
  Bushes  = 0x020, // 000000100000
  Shrubs  = 0x040, // 000001000000
  Trails  = 0x080, // 000010000000
  Ferns   = 0x100, // 000100000000
  Rocks   = 0x200, // 001000000000
  Animals = 0x400, // 010000000000
  Moss    = 0x800, // 100000000000
}

Scan down starting with the right column and notice the pattern 1-2-4-8 (shift) 1-2-4-8 (shift) ...


To answer the original question, I second @Sahuagin's suggestion to use hexadecimal literals. If you're working with binary numbers often enough for this to be a concern, it's worth your while to get the hang of hexadecimal.

If you need to see binary numbers in source code, I suggest adding comments with binary literals like I have above.

Roy Tinker
  • 10,044
  • 4
  • 41
  • 58
  • You can make this even easier like this: ```[Flags] public enum Scenery { Trees = 0x001, Grass = 1 << 1, Flowers = 1 << 2, Cactus = 1 << 3, };``` You just start with 0 or 1, then each one following 1 (starting with 2) simply shifts left by an increasing operand. << 1, << 2, << 3, << 4, << 5, and so on. Easier to do correctly and edit when a big enum needs to be changed. (EDIT: If someone can help format that better, please do) – Aaron Carter Oct 26 '22 at 04:31
25

You can always create quasi-literals, constants which contain the value you are after:

const int b001 = 1;
const int b010 = 2;
const int b011 = 3;
// etc ...
Debug.Assert((b001 | b010) == b011);

If you use them often then you can wrap them in a static class for re-use.

However, slightliy off-topic, if you have any semantics associated with the bits (known at compile time) I would suggest using an Enum instead:

enum Flags
{ 
    First = 0,
    Second = 1,
    Third = 2,
    SecondAndThird = 3
}
// later ...
Debug.Assert((Flags.Second | Flags.Third) == Flags.SecondAndThird);
Markus Johnsson
  • 3,949
  • 23
  • 30
18

If you look at the language feature implementation status of the .NET Compiler Platform ("Roslyn") you can clearly see that in C# 6.0 this is a planned feature, so in the next release we can do it in the usual way.

Binary literal status

totymedli
  • 29,531
  • 22
  • 131
  • 165
3

Binary literal feature was not implemented in C# 6.0 & Visual Studio 2015. but on 30-March 2016 Microsoft announced the new version of Visual Studio '15' Preview with that we can use binary literals.

We can use one or more than one Underscore( _ ) character for digit separators. so the code snippet would look something like:

int x           = 0b10___10_0__________________00; //binary value of 80
int SeventyFive = 0B100_________1011; //binary value of 75

WriteLine($" {x} \n {SeventyFive}");

and we can use either of 0b and 0B as shown in the above code snippet.

if you do not want to use digit separator you can use it without digit separator like below code snippet

int x           = 0b1010000; //binary value of 80
int SeventyFive = 0B1001011; //binary value of 75

WriteLine($" {x} \n {SeventyFive}");
Banketeshvar Narayan
  • 3,799
  • 4
  • 38
  • 46
3
string sTable="static class BinaryTable\r\n{";
string stemp = "";
for (int i = 0; i < 256; i++)
{
stemp = System.Convert.ToString(i, 2);
while(stemp.Length<8) stemp = "0" + stemp;
sTable += "\tconst char nb" + stemp + "=" + i.ToString() + ";\r\n";
}
sTable += "}";
Clipboard.Clear();
Clipboard.SetText ( sTable);
MessageBox.Show(sTable);

Using this, for 8bit binary, I use this to make a static class and it puts it into the clipboard.. Then it gets pasted into the project and added to the Using section, so anything with nb001010 is taken out of a table, at least static, but still... I use C# for a lot of PIC graphics coding and use 0b101010 a lot in Hi-Tech C

--sample from code outpt--

static class BinaryTable
{   const char nb00000000=0;
    const char nb00000001=1;
    const char nb00000010=2;
    const char nb00000011=3;
    const char nb00000100=4;
//etc, etc, etc, etc, etc, etc, etc, 
}

:-) NEAL

Jordan
  • 9,642
  • 10
  • 71
  • 141
Neal
  • 31
  • 1
2

While not possible using a Literal, maybe a BitConverter can also be a solution?

Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • BitConverter gets a bit tricky because it is machine-endian; and on your standard Intel, that means little-endian. Most people have difficulty reading little-endian literals... – Marc Gravell Feb 27 '09 at 13:33
  • 1
    Ouch, now i remember why I was always aware of but never used the BitConverter... – Michael Stum Feb 27 '09 at 15:07
  • 4
    BitConverter has the field `BitConverter.IsLittleEndian`, which you can use to test (and reverse a buffer) if the host machine not little endian. – foxy Jul 19 '11 at 21:12
1

Basically, I think the answer is NO, there is no easy way. Use decimal or hexadecimal constants - they are simple and clear. @RoyTinkers answer is also good - use a comment.

int someHexFlag = 0x010; // 000000010000
int someDecFlag = 8;     // 000000001000

The others answers here present several useful work-a rounds, but I think they aren't better then the simple answer. C# language designers probably considered a '0b' prefix unnecessary. HEX is easy to convert to binary, and most programmers are going to have to know the DEC equivalents of 0-8 anyways.

Also, when examining values in the debugger, they will be displayed has HEX or DEC.

RaoulRubin
  • 518
  • 2
  • 6
  • 18
1

Though the string parsing solution is the most popular, I don't like it, because parsing string can be a great performance hit in some situations.

When there is needed a kind of a bitfield or binary mask, I'd rather write it like

long bitMask = 1011001;

And later

int bit5 = BitField.GetBit(bitMask, 5);

Or

bool flag5 = BitField.GetFlag(bitMask, 5);`

Where BitField class is

public static class BitField
{
    public static int GetBit(int bitField, int index)
    {
        return (bitField / (int)Math.Pow(10, index)) % 10;
    }

    public static bool GetFlag(int bitField, int index)
    {
        return GetBit(bitField, index) == 1;
    }
}
Dmitry Tashkinov
  • 1,976
  • 19
  • 16
1

You can use 0b000001 since Visual Studio 2017 (C# 7.0)

Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
Xiaoyuvax
  • 71
  • 6