C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
These enable us to represent a null, true and false value in a single variable. But we want to know if this is an efficient representation of a three-value variable.
Example. Let's get started with the nullable bool example. To use a nullable bool, use the type "bool?" with the trailing question mark. This is a struct that contains a bool. The "bool?" can be set to null, true and false.
Also: The program shows that each "bool?" occupies 2 bytes in memory. It has an extra byte of overhead beyond a regular bool.
C# program that uses nullable bool
using System;
class Program
{
static void Main()
{
bool? tristate = null;
tristate = true;
tristate = false;
Console.WriteLine(tristate);
long m1 = GC.GetTotalMemory(false);
bool?[] b1 = new bool?[100000];
long m2 = GC.GetTotalMemory(false);
b1[0] = false;
Console.WriteLine("{0} bytes per bool?", (m2 - m1) / 100000);
}
}
Output
False
2 bytes per bool?


Tristate enum. Next, we consider a tristate enum, which can be implemented with a byte backing store. Notice how the semicolon syntax ": byte" is used after the enum type declaration. It can be set to Tristate.Null, Tristate.True and Tristate.False.
Tip: Unlike the nullable bool, all three values can be represented in one byte of storage.
C# program that uses Tristate byte enum
using System;
class Program
{
enum Tristate : byte
{
Null = 0,
True = 1,
False = 2
}
static void Main()
{
Tristate tristate = Tristate.Null;
tristate = Tristate.True;
tristate = Tristate.False;
Console.WriteLine(tristate);
long m1 = GC.GetTotalMemory(false);
Tristate[] b1 = new Tristate[100000];
long m2 = GC.GetTotalMemory(false);
b1[0] = Tristate.False;
Console.WriteLine("{0} byte(s) per Tristate", (m2 - m1) / 100000);
}
}
Output
False
1 byte(s) per Tristate


Summary. Nullable bools can represent three values: null, false and true. But as we saw here, a custom enum type that uses a byte backing store can more efficiently represent these three values. In type safety the approaches are equally effective.
However: The enum type avoids the overhead associated with wrapping a value type in a generic struct.