5

Just playing around with C# 8.0 Beta and updating some of my code to use nullable reference types.

I have a node style class for a Trie implementation. Each node has a value of type T. The constructor for the root node does not need a value, so I was setting this to default.

Here's a short version:

public class Trie<T>
{
    public readonly bool caseSensitive;
    public readonly char? letter;
    public readonly Dictionary<char, Trie<T>> children;
    public readonly Trie<T>? parent;
    public readonly int depth;
    public bool completesString;
    public T value;

    public Trie(bool caseSensitive = false)
    {
        this.letter = null;
        this.depth = 0;
        this.parent = null;
        this.children = new Dictionary<char, Trie<T>>();
        this.completesString = false;
        this.caseSensitive = caseSensitive;
        this.value = default;
    }
}

if the last line of the ctor is changed to

   this.value = default!;

as I saw in a different question here, then it compiles just fine. But I don't understand what the ! is doing here, and it's pretty hard to google, since google seems to ignore punctuation in most cases.

What does default! do?

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
craig
  • 421
  • 4
  • 13

2 Answers2

7

The nullable reference types use static flow analysis to figure out if you have a possible null value (thus issuing a warning the variable is being assigned a null value).

The ! is used to allow the developer to suppress the warning generated. Essentially overriding the compiler.

Adam Carr
  • 678
  • 4
  • 13
  • 1
    The accepted term appears to be "Null Forgiveness Operator" – BlueMonkMN Apr 04 '19 at 22:58
  • 2
    I have also heard it called the "Damm it Operator" (as in: 'it's not null Damm it!) (Attribution: Mads Torgersen) This term was probably not 'accepted' by legal... – DarcyThomas Apr 04 '19 at 23:19
3

It doesn't do anything. If you have a look at the IL generated for each method it is the same. "Nullable Reference Types" is that is a compile time warning/error to ensure that developers have explicitly flagged variables as potentially being assigned a null value. If a variable has been assigned a value with the ! flag then the compiler will not warn anytime the variable is de-referenced without checking for null value.

As T has no constraints it will emit a warning Warning

Warning will be removed if you replace default with default! which is the equivalent of saying null! for reference types which is self-defeating; For value types default is never null so it is doubly self-defeating.

Additionally, if you use GenericClass<T> where T : struct, default will not emit a warning.

using System;
using System.Collections.Generic;

namespace TestingGround
{
    public class Program
    {
        public class GenericClass<T>
        {
            public T Value;


            public GenericClass()
            {
                Value = default;
            }
        }

        static void Main(string[] args)
        {
            var gc = new GenericClass<string>();
            var strLength = gc.Value.Length;
        }
    }
}

IL

      IL_0008: ldarg.0      // this
      IL_0009: ldflda       !0/*T*/ class TestingGround.Program/GenericClass`1<!0/*T*/>::Value
      IL_000e: initobj      !0/*T*/
user1378730
  • 930
  • 9
  • 18