Skip to content

Instantly share code, notes, and snippets.

@richlander
Last active November 9, 2020 07:08
Show Gist options
  • Save richlander/ca6567039906da4e1fcfba557b6ccb63 to your computer and use it in GitHub Desktop.
Save richlander/ca6567039906da4e1fcfba557b6ccb63 to your computer and use it in GitHub Desktop.
Testing nullability with arrays
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
using System;
using static System.Console;
// Goal: test various combinations of nullability and non-nullability with arrays.
// I was having some trouble working out the syntax for nullability with arrays.
// I ended up at: https://www.reddit.com/r/csharp/comments/dd2ljw/nullable_reference_types_and_arrays/
// This test is intended to demonstrate the syntax and behavior of nullable reference types and arrays (obviously).
// The test code is the same for each test. Where the code isn't appropriate (won't compile), the code is just commented out.
// I used scopes so that I could use the same variable names throughout.
// The point isn't that the tests return different results (that's inherent in the code that was written),
// but in the pattern that is used to make the same(ish) code work correctly for all four combinations.
// There are four tests:
// - Nullable array variable with nullable elements
// - Nullable array variable with non-nullable elements
// - Non-nullable array variable with nullable elements
// - Non-nullable Array variable with non-nullable elements
// Do you have to use and know all four of these combinations to use nullable reference types and arrays?
// Yes. You don't have to learn and remember the combinations.
// You just need to know one main thing. There are two places to put the nullable '?' operator with arrays (using string[] as the example):
// string?[]? stringArray;
// The first `?` is refering to the string elements in the array. The second one is referring to the aray itself.
// We can compare this to a non-array type like string.
// string? myString;
// In this case, since string is not an array (ignoring the fact that it exposes an idexer of type char), the `?` that it is marked with
// is the same as the second `?` with stringArray, not the first. The first one (in the middle, not the end, of the type definition)
// is unique to arrays.
{
// Test 1
string description = "Nullable array variable with nullable elements";
WriteLine($"**{description}**");
string?[]? stringArray = null;
Write($"Test: is {nameof(stringArray)} an object? Answer: ");
if (stringArray is object)
{
WriteLine($"Yes; Length: {stringArray.Length}");
}
else
{
WriteLine("No");
}
stringArray = new string[2];
stringArray[0] = description;
stringArray[0] = null;
Write($"Test: is {nameof(stringArray)}[0] an object? Answer: ");
if (stringArray[0] is object)
{
WriteLine($"Yes; Value: {stringArray[0]}; Length: {stringArray[0]!.Length}");
}
else
{
WriteLine("No");
}
Write($"Test: is {nameof(stringArray)}[1] an object? Answer: ");
if (stringArray[1] is object)
{
WriteLine($"Yes; Value: {stringArray[1]}; Length: {stringArray[1]!.Length}");
}
else
{
WriteLine("No");
}
stringArray = null;
string? element = stringArray?[0];
Write($"Test: is {nameof(element)} an object? Answer: ");
if (element is object)
{
element = description;
WriteLine($"Yes; Value: {element}; Length: {element.Length}");
}
else
{
WriteLine("No");
}
}
{
// Test 2
string description = "Nullable array variable with non-nullable elements";
WriteLine($"**{description}**");
string[]? stringArray = null;
Write($"Test: is {nameof(stringArray)} an object? Answer: ");
if (stringArray is object)
{
WriteLine($"Yes; Length: {stringArray.Length}");
}
else
{
WriteLine("No");
}
stringArray = new string[2];
stringArray[0] = description;
// stringArray[0] = null;
Write($"Test: is {nameof(stringArray)}[0] an object? Answer: ");
if (stringArray[0] is object)
{
WriteLine($"Yes; Value: {stringArray[0]}; Length: {stringArray[0]!.Length}");
}
else
{
WriteLine("No");
}
Write($"Test: is {nameof(stringArray)}[1] an object? Answer: ");
if (stringArray[1] is object)
{
WriteLine($"Yes; Value: {stringArray[1]}; Length: {stringArray[1]!.Length}");
}
else
{
WriteLine("No");
}
stringArray = null;
string? element = stringArray?[0];
Write($"Test: is {nameof(element)} an object? Answer: ");
if (element is object)
{
element = description;
WriteLine($"Yes; Value: {element}; Length: {element.Length}");
}
else
{
WriteLine("No");
}
}
{
// Test 3
string description = "Non-nullable array variable with nullable elements";
WriteLine($"**{description}**");
string?[] stringArray = new string[2];
Write($"Test: is {nameof(stringArray)} an object? Answer: ");
if (stringArray is object)
{
WriteLine($"Yes; Length: {stringArray.Length}");
}
else
{
WriteLine("No");
}
stringArray = new string[2];
stringArray[0] = description;
stringArray[0] = null;
Write($"Test: is {nameof(stringArray)}[0] an object? Answer: ");
if (stringArray[0] is object)
{
WriteLine($"Yes; Value: {stringArray[0]}; Length: {stringArray[0]!.Length}");
}
else
{
WriteLine("No");
}
Write($"Test: is {nameof(stringArray)}[1] an object? Answer: ");
if (stringArray[1] is object)
{
WriteLine($"Yes; Value: {stringArray[1]}; Length: {stringArray[1]!.Length}");
}
else
{
WriteLine("No");
}
// stringArray = null;
string? element = stringArray?[0];
Write($"Test: is {nameof(element)} an object? Answer: ");
if (element is object)
{
element = description;
WriteLine($"Yes; Value: {element}; Length: {element.Length}");
}
else
{
WriteLine("No");
}
}
{
// Test 4
string description = "Non-nullable Array variable with non-nullable elements";
WriteLine($"**{description}**");
string[] stringArray = new string[2];
Write($"Test: is {nameof(stringArray)} an object? Answer: ");
if (stringArray is object)
{
WriteLine($"Yes; Length: {stringArray.Length}");
}
else
{
WriteLine("No");
}
stringArray = new string[2];
stringArray[0] = description;
// stringArray[0] = null;
Write($"Test: is {nameof(stringArray)}[0] an object? Answer: ");
if (stringArray[0] is object)
{
WriteLine($"Yes; Value: {stringArray[0]}; Length: {stringArray[0]!.Length}");
}
else
{
WriteLine("No");
}
Write($"Test: is {nameof(stringArray)}[1] an object? Answer: ");
if (stringArray[1] is object)
{
WriteLine($"Yes; Value: {stringArray[1]}; Length: {stringArray[1]!.Length}");
}
else
{
WriteLine("No");
}
// stringArray = null;
string? element = stringArray?[0];
Write($"Test: is {nameof(element)} an object? Answer: ");
if (element is object)
{
element = description;
WriteLine($"Yes; Value: {element}; Length: {element.Length}");
}
else
{
WriteLine("No");
}
}
@richlander
Copy link
Author

Results

**Nullable array variable with nullable elements**
Test: is stringArray an object? Answer: No
Test: is stringArray[0] an object? Answer: No
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: No
**Nullable array variable with non-nullable elements**
Test: is stringArray an object? Answer: No
Test: is stringArray[0] an object? Answer: Yes; Value: Nullable array variable with non-nullable elements; Length: 50
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: No
**Non-nullable array variable with nullable elements**
Test: is stringArray an object? Answer: Yes; Length: 2
Test: is stringArray[0] an object? Answer: No
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: No
**Non-nullable Array variable with non-nullable elements**
Test: is stringArray an object? Answer: Yes; Length: 2
Test: is stringArray[0] an object? Answer: Yes; Value: Non-nullable Array variable with non-nullable elements; Length: 54
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: Yes; Value: Non-nullable Array variable with non-nullable elements; Length: 54
PS D:\git\testapps\nullablearrays> dotnet run
**Nullable array variable with nullable elements**
Test: is stringArray an object? Answer: No
Test: is stringArray[0] an object? Answer: No
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: No
**Nullable array variable with non-nullable elements**
Test: is stringArray an object? Answer: No
Test: is stringArray[0] an object? Answer: Yes; Value: Nullable array variable with non-nullable elements; Length: 50
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: No
**Non-nullable array variable with nullable elements**
Test: is stringArray an object? Answer: Yes; Length: 2
Test: is stringArray[0] an object? Answer: No
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: No
**Non-nullable Array variable with non-nullable elements**
Test: is stringArray an object? Answer: Yes; Length: 2
Test: is stringArray[0] an object? Answer: Yes; Value: Non-nullable Array variable with non-nullable elements; Length: 54
Test: is stringArray[1] an object? Answer: No
Test: is element an object? Answer: Yes; Value: Non-nullable Array variable with non-nullable elements; Length: 54

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment