Can a non-nullable reference type in C# 8 be null

2020-08-20 09:09发布

It seems to me there is really no guarantee that a non-nullable variable won't ever have null. Imagine I have a class that has one property that is not nullable:

public class Foo
{
    public Foo(string test)
    {
        Test = test;
    }
    public string Test {get;set;}
}

Now that might seem like it's now cannot be null. But if we reference this class with another library that does not use nullable context, nothing stops it from sending null in there.

Is that correct or there are some runtime checks as well perhaps that ensure this?

5条回答
够拽才男人
2楼-- · 2020-08-20 09:48

Even in your own code, if you choose to do so, you can pass null, using the null-forgiving operator. null! is considered to be not-null so far as the compiler's nullability analysis is concerned.

查看更多
3楼-- · 2020-08-20 09:51

This is what MS says about (https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code):

The compiler can't validate all calls to your public APIs, even if your code is compiled with nullable annotation contexts enabled. Furthermore, your libraries may be consumed by projects that have not yet opted into using nullable reference types. Validate inputs to public APIs even though you've declared them as nonnullable types.

查看更多
Melony?
4楼-- · 2020-08-20 10:03

You are correct, other code which is not using the new feature could assign null to this property, there are no run-time checks it is just complier hints.

You could always do it yourself if you want a runtime check:

public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }

Note that you can guarantee not being null in most of your code, you just need to add guards to your top-level Public API and make sure classes are appropriately sealed etc.

Of course people can still use reflection to f*** your code up, but then its on them

查看更多
乱世女痞
5楼-- · 2020-08-20 10:15

someone can always do

var myFoo = new Foo(null);

May be you can use Domain Driven Design

public class Foo
{
    public Foo(string test)
    {
         if (string.IsNullOrWhiteSpace(test))
             throw new ArgumentNullException(nameof(test));

         Test = test;
    }
    public string Test {get;private set;}
}
查看更多
\"骚年 ilove
6楼-- · 2020-08-20 10:15

To deal with null checks and also make your code readable, I suggest Null Object Design pattern.

More reading here:

https://www.c-sharpcorner.com/article/null-object-design-pattern/

Basically, it involves creating a new object which is derived from same interface and has null instance.

Example:

public class NullExample : IExample  
{  
    private static NullExample _instance;  
    private NullExample()  
    { }  

    public static NullExample Instance  
    {  
        get {  
            if (_instance == null)  
                return new NullExample();  
            return _instance;  
        }  
    }  

    //do nothing methods  
    public void MethodImplementedByInterface1()  
    { }  

    public void MethodImplementedByInterface1()  
    { }  
}  

Nulls cant be avoided, however they can be checked cleanly.

查看更多
登录 后发表回答