kota's memex

new

The following declares a variable which could hold a reference, or memory address of a value in the heap. It's a null reference as it does not currently point anywhere.

int[] data;

If we add the following:

int[] data;
data = new int[3];

The new keyword creates an instance of an int array, allocating and storing it in the heap. Finally, the memory address is stored in the variable data.

The ints elements are defaulted to 0 as that is the default value for int.

strings

Strings are also reference types, but the new keyword is not required because the data type is used so frequently.

practical considerations

In this example two variables are created storing the address of a single array. Changing the value in one of these references changes it for both.

int[] ref_A = new int[1];
ref_A[0] = 2;
int[] ref_B = ref_A;
ref_B[0] = 5;

Console.WriteLine("--Reference Types--");
Console.WriteLine($"ref_A[0]: {ref_A[0]}"); // Prints 5
Console.WriteLine($"ref_B[0]: {ref_B[0]}"); // Prints 5

null

Any reference can be null and can be created explicitly:

string name = null;

They're helpful for indicating that there is no data available. Null is the default value for reference types.

Trying to use a null value causes a runtime error:

string name = null;
Console.WriteLine(name.Length); // Crashes!

null annotation

Using the ? annotation you can indicate that a variable might be null:

string? name = Console.ReadLine(); // Can return null!
if (name != null)
  Console.WriteLine("This name is not null");

null conditional operators

In the following code _scoreManager, GetScores(), or even [0] could all individually be null:

private string? GetTopPlayerName()
{
  return _scoreManager.GetScores()[0].Name;
}

If you don't want to add a bunch of if statements you can use the following syntax to check each variable and return null if any individual part is null:

private string? GetTopPlayerName()
{
  return _scoreManager?.GetScores()?[0]?.Name;
}

null coalescing operator

The null coalescing operator ?? takes an expression that might be null and allows you to provide a value in the case that it is. It's another if statement shorthand basically. Often used when you don't want a function to return with a possible null:

private string GetTopPlayerName()
{
  return _scoreManager?.GetScores()?[0]?.Name ?? "unknown";
}

null forgiving operator

Sometimes you need to tell the compiler that "although this looks like it could be null" it will not be null. The null forgiving operator ! can be used:

string message = NullIfNegative(+10)!;