Why does null exist in .NET?

前端 未结 11 1511
醉酒成梦
醉酒成梦 2020-12-24 06:04

Why can values be null in .NET? Is this superior to having a guarantee where everything would have a value and nothing call be null?

Anyone knows what each of these

相关标签:
11条回答
  • 2020-12-24 06:30

    To denote the nothingness concept, since 0 is not the right fit.

    Now you can give any value type a Null value by defining a nullable type.

    I think we can't have a value always for the variable because at first we have to default it to some value, and here comes the question why a specific value takes advantage over the others.

    0 讨论(0)
  • 2020-12-24 06:30

    Many people probably can't wrap their head around coding without nulls, and if C# didn't have nulls, I doubt it would have caught on to the extent that it has.

    That being said, a nice alternative would be, if you want to allow a nullable reference, then the reference would have to be explicitly nullable, like with value types.

    For example,

    Person? person = SearchForPersonByFirstName("Steve");
    if (person.HasValue)
    {
        Console.WriteLine("Hi, " + person.Value.FullName);
    }
    

    Unfortunately, when C# 1.0 came out, there was no concept of Nullable; that was added in C# 2.0. Forcing references to have values would have broken the older programs.

    0 讨论(0)
  • 2020-12-24 06:33

    Well, values (value-type vars) can only be null since the nullable types were introduced in Fx2.

    But I suppose you mean:

    Why can references be null ?

    That is part of the usefulness of references. Consider a Tree or LinkedList, they would not be possible (unable to end) without null.

    You could come up with many more examples, but mainly null exists to model the concept of 'optional' properties/relationships.

    0 讨论(0)
  • 2020-12-24 06:36

    null is just the name of the default value for a reference type. If null was not allowed, then the concept of "doesn't have a value" wouldn't go away, you would just represent it in a different way. In addition to having a special name, this default value also has special semantics in the event that it is misused - i.e. if you treat it like there is a value, when in fact there is not.

    If there were no null:

    1. You would need to define sentinel default values for your types to use when "there is no value". As a trivial example, consider the last node of a forward singly-linked list.
    2. You would need to define semantics for operations performed on all of these sentinel values.
    3. The runtime would have additional overhead for handling the sentinel values. In modern virtual machines such as the ones used by .NET and Java, there is no overhead for null-checking prior to most function calls and dereferences because the CPU provides special ways to handle this case, and the CPU is optimized for cases where the references are non-null (e.g. branch prediction).

    In summary:

    • The name would change, but the concept would not.
    • The burden of defining and communicating the default value and semantics for cases where you have "no value" is placed on developers and developer documentation.
    • Code executing on modern virtual machines would face code bloat and substantial performance degradation for many algorithms.

    The problems with null described by Tony Hoare are typically due to the fact that prior to modern virtual machines, runtime systems did not have nearly as clean handling of misused null values like you have today. Misusing pointers/references does remain a problem, but tracking down the problem when working with .NET or Java tends to be much easier than it used to be in e.g. C.

    0 讨论(0)
  • 2020-12-24 06:39

    Ok now wrap to the magic word of C#-without-null

    class View
    {
        Model model;        
    
        public View(Model model)
        {
            Console.WriteLine("my model : {0}, thing : {1}", this.model, this.model.thing);
            this.model = model;
        }
    }
    

    What is printed on the console?

    • Nothing an exception about accessing an un-initialized object is thrown : Ok call this a NullReferenceException and that's the current world.
    • It doesn't build, the user needed to specify a value when declaring model, see last bullet point as it create the same result.
    • Some default for the model and some default for the thing : Ok before with null we at least had a way to know if an instance was correct now the compiler is generating strange look-alikes that don't contain anything but are still invalid as model objects...
    • Something defined by the type of the objects : Better as we could define a specific invalid state per object but now each object that could be invalid need to independently implement this along with a way to identify this state by the caller...

    So basically for me it don't seem to solve anything to remove a null state, as the possibly invalid state still need to be managed anyway...

    Oh buy the way what would be the default value of an interface ? Oh and an abstract class what would happen when a method is called on a default value that is defined in the abstract class but that call another method that is abstract ? .... .... Why oh why complicating the model for nothing, it's multiple-inheritance questions all over again !

    One solution would be to change the syntax completely to go for a full functional one where the null world doesn't exits, only Maybes when you want them to exists... But it's not a C like language and the multi-paradigm-ness of .Net would be lost.

    What might be missing is a null-propagating operator able to return null to model.Thing when model is null, like model.?.Thing


    Oh and for good mesure an answer to your question :

    • The current class library evolved after the Microsoft-Java debacle and C# was build as a "better-Java" so changing the type system to remove null references would have been a big change. They already manage to introduce value types and removed manual boxing !
    • As the value type introduction show microsoft think a lot about speed... The fact that the the default for all types map to a zero fill is really important for fast array initialization for example. Otherwise initialization of arrays of reference values would have need special threatment.
    • Without null interop with C would not have been possible so at least at the MSIL level and in unsafe block they need to be allowed to survive.
    • Microsoft wanted to use the framework for VB6++ removing Nothing as it is called in VB would have radically changed the language, it already took years for users to switch from VB6 to VB.Net such a paradigm change might have been fatal for the language.
    0 讨论(0)
提交回复
热议问题