Null references redux

Daniel Keep daniel.keep.lists at gmail.com
Sat Sep 26 18:44:30 PDT 2009



Walter Bright wrote:
> ...
> 
> It all depends on what you prefer a program to do when it encounters a
> program bug:
> 
> 1. Immediately stop and produce an indication that the program failed
> 
> 2. Soldier on and silently produce garbage output
> 
> I prefer (1).
> 
> ...

*sigh*  Walter, I really admire you as a programmer.  But this is about
the most blatant strawman argument I've seen in a while.

Firstly, as others have indicated, the whole point of non-null would be
to REQUIRE initialisation to something useful.

"But the user will just assign to something useless to get around that!"

You mean like how everyone wraps every call in try{...}catch(Exception
e){} to shut the damn exceptions up?  Or uses pointer arithmetic and
casts to get at those pesky private members?

If someone is actively trying to break the type system, it's their
goddamn fault!  Honestly, I don't care about the hacks they employ to
defeat the system because they're going to go around blindly shooting
themselves in the foot no matter what they do.

It's like arguing that safety rails are pointless because people can
just jump over them.  BESIDES, if they fall off, you get this really
loud "crunch" followed by a shower of blood; then it's OBVIOUS that
something's wrong.

And what about the people who AREN'T complete idiots, who maybe
sometimes just accidentally trip and would quite welcome a safety rail
there?

Besides which, the non-null proposal is always accompanied by the
proposal to add nullable object references as T? (or whatever; the
syntax is irrelevant at this point).  If a programmer really wants a
null-initialised object reference, which is she more likely to do?

  class NullFoo : Foo
  {
    void member1() { throw new Exception("NULL!"); }
    void member2() { throw new Exception("NULL!"); }
    ...
  }

  Foo bar = new NullFoo;

or

  Foo? bar;

Since the reason they're trying to circumvent the non-null protection is
because of laziness, I assert they're far more likely to go with the
second than the first.

And it's STILL better because you couldn't implicitly cast between Foo?
and Foo.  They would HAVE to insert an explicit cast or check.

  Foo quxx = enforceNN(bar);

Finally, let me re-post something I wrote the last time this came up:

> The problem with null dereference problems isn't knowing that they're
> there: that's the easy part.  You helpfully get an exception to the
> face when that happens. The hard part is figuring out *where* the
> problem originally occurred. It's not when the exception is thrown
> that's the issue; it's the point at which you placed a null reference
> in a slot where you shouldn't have.
>
> Yes, we have invariants and contracts; but inevitably you're going to
> forget one, and it's that one slip-up that's going to bite you in the
> rear.
>
> One could use roughly the same argument for non-null references as for
> const: you could document it, but documentation is inevitably wrong or
> out of date.  :P



More information about the Digitalmars-d mailing list