Search code examples
c#-8.0nullable-reference-types

Why is it still possible to assign null to non nullable reference type?


I am confused. I thought enabling c# 8 and nullable reference types will prevent the assignment of null to a non nullable reference types, but apparently it is only a warning at compile time, I know you can enforce it to be an error and stop it build, but I thought it is more than just a compiler check.

Look at this example https://dotnetfiddle.net/4eCs5L

If you run, it is still possible to assign null to non nullable reference type, why isn't that throwing an error at run time?


Solution

  • The purpose of the feature is to give developers more tools to catch the most prevalent type of errors there is, derefencing a null reference / pointer and thus crashing the application.

    As such, the C# design team added "nullable reference types", with enough syntax that the developer can more clearly declare the intent and requirements of code.

    Things that can be expressed by the new syntax:

    • Properties and fields that either allow NULL or does not allow NULL
    • Method parameters that can be NULL, or should be NULL
    • Method return values that can be NULL, or won't be NULL

    When enabled, the compiler will use this new syntax, and attributes and other metadata, to start giving warnings when it sees code that isn't "guaranteed" to be correct. In other words, if you read a property that says it can return NULL, and try to just pass that in as a parameter value where the method says that the parameter shouldn't be NULL, you will get a warning.

    You can, using existing directives on projects, say that certain warnings should instead be handled as errors, and break the build, and this includes these new warnings.

    HOWEVER, what they didn't add was runtime checks. If you say that a parameter value should never be NULL, and either ignore the warning or bypass it (there are ways to say "trust me, this is correct"), then the method will run as stated. There are no invisible if-statements or guard statements that verify that the parameter is not null.

    Basically, you should still add such if-statements.

    This is, contrary to your belief, exactly what they designed the feature to do. They did not forget to add these runtime checks, they purposefully didn't add them.

    For instance, if you call a method through reflection, the compiler is not involved since it is a runtime thing, and thus no checks will be performed at all. If the method doesn't have such guard statements, likely it will crash later with a NullReferenceException.