4

Using C# in .NET 6.0 I am coming across warnings which say "Cannot convert null literal to non-nullable reference type." Which I thought classes were nullable and were able to be set as null...

This produces the Warning:

    public class Foo
    {
        public string Name { get; set; }

        public Foo()
        {
            Name = "";
        }
    }

    public class Bar
    {
        public Foo fooClass;

        public Bar()
        {
            // Because I don't want to set it as anything yet.
            fooClass = null;
        }

        public void FooBarInit()
        {
            fooClass = new Foo();
        }
    }

But doing this gives me no warning

    public class Foo
    {
        public string Name { get; set; }

        public Foo()
        {
            Name = "";
        }
    }

    public class Bar
    {
        public Foo? fooClass;

        public Bar()
        {
            // Because I don't want to set it as anything yet.
            fooClass = null;
        }

        public void FooBarInit()
        {
            fooClass = new Foo();
        }
    }

However now lets attempt to use the Name variable in Foo inside of Bar

    public class Foo
    {
        public string Name { get; set; }

        public Foo()
        {
            Name = "";
        }
    }

    public class Bar
    {
        public Foo? fooClass;

        public Bar()
        {
            // Because I don't want to set it as anything yet.
            fooClass = null;
        }

        public void FooBarInit()
        {
            fooClass = new Foo();
        }

        public void FooBarTest()
        {
            Console.WriteLine(fooClass.Name); // Warning here which tells me fooClass maybe null
        }
    }

However FooBarTest will never run without the FooBarInit being ran first. So it'll never be null and if it is, I would have an error handling situation after that.

My question is, why do I have to set classes to allow null when they should inherently accept null anyway?

If I use the "?" after declaring a class... I now have to check if it's null... ANY time I want to call that class, it makes my code look atrocious. Any fixes or ability to turn it off?

ShadowEvil
  • 43
  • 4
  • https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references – gunr2171 Oct 13 '22 at 21:52
  • See here: https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references. Starting with .NET 6, for new projects nullable reference types/nullable context are enabled by default. –  Oct 13 '22 at 21:52

2 Answers2

4

Although it's a very nice feature, you can still disable it by changing the value of the Nullable property to disable in your .csproj file:

  <PropertyGroup>
    ...
    <Nullable>disable</Nullable>
    ...
  </PropertyGroup>
M. Mennan Kara
  • 10,072
  • 2
  • 35
  • 39
  • I will admit, it is a nifty feature for Crash preventions but it should be left up to the programmer to decide... However wonder why there's no way to disable it in the actual properties in Visual Studio. Thanks again btw – ShadowEvil Oct 13 '22 at 21:59
  • @ShadowEvil In VS2022 in the projects properties in Build -> General there is a Nullable setting. – Jonathan Dodds Oct 13 '22 at 22:01
  • @JonathanDodds Thanks! I prefer not to go messing about in a generated file! lol – ShadowEvil Oct 13 '22 at 22:03
  • There is a project setting in the UI for it, actually. It’s under Build > General. – Vivelin Oct 14 '22 at 06:38
  • @ShadowEvil Visual Studio's .*proj files are MSBuild and are designed to be both edited by hand and updated by the IDE. It is safe to mess about in the project file. – Jonathan Dodds Oct 14 '22 at 16:51
3

If you know that the value of a nullable type cannot possibly be null, you can use the null-forgiving operator.

Console.WriteLine(fooClass!.Name);

You can also (bizarrely to this Kotlin dev) assign null to a non-nullable type using this mechanism:

public Foo fooClass = null!;

This answer suggests it's similar to using lateinit in Kotlin, which says to the compiler "I promise this will have been set to something non-null by the time I come to use it". You can initialize the variable to null with this technique, but you can't set it to null later on.

Lunivore
  • 17,277
  • 4
  • 47
  • 92