Here's how Haskell does it: (not exactly a counter to Lippert's statements since Haskell is not an Object-Oriented language).

WARNING: long winded-answer from a serious Haskell fanboy ahead.

TL;DR

This example illustrates exactly how different Haskell is from C#. Instead of delegating the logistics of structure construction to a constructor, it must be handled in the surrounding code. There is no way for a null (Or Nothing in Haskell) value value to crop up where we are expecting a non-null value because null values can only occur within special wrapper types called Maybe which are not interchangeable with/directly convertible to regular, non-nullable types. In order to use an value made nullable by wrapping it in a Maybe , we must first extract the value using pattern matching, which forces us to divert control flow into a branch where we know for certain that we have a non-null value.

Therefore:

can we always know that a non-nullable reference is never under any circumstances observed to be invalid?

Yes. Int and Maybe Int are two completely separate types. Finding Nothing in a plain Int would be comparable to finding the string "fish" in an Int32 .

What about in the constructor of an object with a non-nullable field of reference type?

Not an issue: value constructors in Haskell can't do anything but take the values they're given and put them together. All initialization logic takes place before the constructor is called.

What about in the finalizer of such an object, where the object is finalized because the code that was supposed to fill in the reference threw an exception?

There are no finalizers in Haskell, so I can't really address this. My first response still stands, however.

Full Answer:

Haskell has no null and uses the Maybe data type to represent nullables. Maybe is an algabraic data type defined like this:

data Maybe a = Just a | Nothing

For those of you unfamiliar with Haskell, read this as "A Maybe is either a Nothing or a Just a ". Specifically:

Maybe is the type constructor: it can be thought of (incorrectly) as a generic class (where a is the type variable). The C# analogy is class Maybe<a>{} .

is the type constructor: it can be thought of (incorrectly) as a generic class (where is the type variable). The C# analogy is . Just is a value constructor: it is a function that takes one argument of type a and returns a value of type Maybe a that contains the value. So the code x = Just 17 is analogous to int? x = 17; .

is a value constructor: it is a function that takes one argument of type and returns a value of type that contains the value. So the code is analogous to . Nothing is another value constructor, but it takes no arguments and the Maybe returned has no value other than "Nothing". x = Nothing is analogous to int? x = null; (assuming we constrained our a in Haskell to be Int , which can be done by writing x = Nothing :: Maybe Int ).

Now that the basics of the Maybe type are out of the way, how does Haskell avoid the issues discussed in the OP's question?

Well, Haskell is really different from most of the languages discussed so far, so I'll begin by explaining a few basic language principles.

First off, in Haskell, everything is immutable. Everything. Names refer to values, not to memory locations where values can be stored (this alone is an enormous source of bug elimination). Unlike in C#, where variable declaration and assignment are two separate operations, in Haskell values are created by defining their value (eg x = 15 , y = "quux" , z = Nothing ), which can never change. Therefore, code like:

ReferenceType x;

Is not possible in Haskell. There are no problems with initializing values to null because everything must be explicitly initialized to a value in order for it to exist.

Secondarily, Haskell is not an object-oriented language: it is a purely functional language, so there are no objects in the strict sense of the word. Instead, there are simply functions (value constructors) that take their arguments and return an amalgamated structure.

Next, there is absolutely no imperative style code. By this, I mean that most languages follow a pattern something like this:

do thing 1 add thing 2 to thing 3 do thing 4 if thing 5: do thing 6 return thing 7

Program behavior is expressed as a series of instructions. In Object-Oriented languages, class and function declarations also play a huge role in program flow, but is essence, the "meat" of a program's execution takes the form of a series of instructions to be executed.

In Haskell, this is not possible. Instead, program flow is dictated entirely by chaining functions. Even the imperative-looking do -notation is just syntactic sugar for passing anonymous functions to the >>= operator. All functions take the form of:

<optional explicit type signature> functionName arg1 arg2 ... argn = body-expression

Where body-expression can be anything that evaluates to a value. Obviously there are more syntax features available but the main point is the complete absence of sequences of statements.

Lastly, and probably most importantly, Haskell's type system is incredibly strict. If I had to summarize the central design philosophy of Haskell's type system, I would say: "Make as many things as possible go wrong at compile time so as little as possible goes wrong at runtime." There are no implicit conversions whatsoever (want to promote an Int to a Double ? Use the fromIntegral function). The only to possibly have an invalid value occur at runtime is to use Prelude.undefined (which apparently just has to be there and is impossible to remove).

With all of this in mind, let's look at amon's "broken" example and try to re-express this code in Haskell. First, the data declaration (using record syntax for named fields):

data NotSoBroken = NotSoBroken {foo :: Foo, bar :: Bar }

( foo and bar are really accessor functions to anonymous fields here instead of actual fields, but we can ignore this detail).

The NotSoBroken value constructor is incapable of taking any action other than taking a Foo and a Bar (which are not nullable) and making a NotSoBroken out of them. There is no place to put imperative code or even manually assign the fields. All initialization logic must take place elsewhere, most likely in a dedicated factory function.

In the example, the construction of Broken always fails. There is no way to break the NotSoBroken value constructor in a similar fashion (there is simply nowhere to write the code), but we can create a factory function that is similarly defective.

makeNotSoBroken :: Foo -> Bar -> Maybe NotSoBroken makeNotSoBroken foo bar = Nothing

(the first line is a type signature declaration: makeNotSoBroken takes a Foo and a Bar as arguments and produces a Maybe NotSoBroken ).

The return type must be Maybe NotSoBroken and not simply NotSoBroken because we told it to evaluate to Nothing , which is a value constructor for Maybe . The types simply wouldn't line up if we wrote anything different.

Aside from being absolutely pointless, this function doesn't even fulfill its real purpose, as we'll we see when we try to use it. Let's create a function called useNotSoBroken which expects a NotSoBroken as an argument:

useNotSoBroken :: NotSoBroken -> Whatever

( useNotSoBroken accepts a NotSoBroken as an argument and produces a Whatever ).

And use it like so:

useNotSoBroken (makeNotSoBroken)

In most language, this sort of behavior might cause a null pointer exception. In Haskell, the types don't match up: makeNotSoBroken returns a Maybe NotSoBroken , but useNotSoBroken expects a NotSoBroken . These types are not interchangeable, and the code fails to compile.

To get around this, we can use a case statement to branch based on the structure of the Maybe value (using a feature called pattern matching):

case makeNotSoBroken of Nothing -> --handle situation here (Just x) -> useNotSoBroken x

Obviously this snippet needs to placed inside some context to actually compile, but it demonstrates the basics of how Haskell handles nullables. Here is a step-by-step explanation of the above code:

First, makeNotSoBroken is evaluated, which is guaranteed to produce a value of type Maybe NotSoBroken .

is evaluated, which is guaranteed to produce a value of type . The case statement inspects the structure of this value.

statement inspects the structure of this value. If the value is Nothing , the "handle situation here" code is evaluated.

, the "handle situation here" code is evaluated. If the value instead matches against a Just value, the other branch is executed. Note how the matching clause simultaneously identifies the value as a Just construction and binds its internal NotSoBroken field to a name (in this case, x ). x can then be used like the normal NotSoBroken value that is.

So, pattern matching provides a powerful facility for enforcing type safety, since the structure of the object is inseparably tied to the branching of control.

I hope this was a comprehensible explanation. If it doesn't make sense, jump into Learn You A Haskell For Great Good!, one of the best online language tutorials I've ever read. Hopefully you will see the same beauty in this language that I do.