I have a Fit, but a lack of Focus.
Here's a statement I read the other day about making comparisons between objects of reference type in C#:
Object.ReferenceEquals(x,y) returns true if and only if x and y refer to the same object.
True or false?
My wife Leah recently acquired a Honda Fit, thanks to the imminant failure of the automatic transmission solenoids in her aged Honda Civic. The back seats in the Fit fold down flat. You can fit a llama or a whole pile of hula hoops or whatever into that thing. It's quite handy. Not what I would call a powerful engine by any means, but for quick trips around town, it certainly gets the job done.
Since we were married when she bought the car, and we continue to be married, what's mine is hers and what's hers is mine. So if x = Eric's Honda Fit, and y = Leah's Honda Fit, then x and y are "reference equals". Those two things refer to the same object, viz, the shiny black object full of llamas and hula hoops in my driveway.
Now, we could have bought a different car. Say, a Ford Focus. But we did not. We own a total of zero Ford Foci. Suppose I said that x = Eric's Ford Focus, and y = Leah's Ford Focus. What's the sensible way to characterize the nature of x and y? Do we say that x and y refer to the same Ford Focus, namely that they refer to the Ford Focus that does not exist? The mind boggles at the repugnant and paradoxical implication that there exists a Ford Focus that is the Ford Focus that does not exist! (*) Rather, the right way to characterize this is to say that neither x nor y refer to any object. They're "null references" -- references that do not have any referent, but rather, capture the notion of "a lack of referent".
And that's why it's incorrect to say that Object.ReferenceEquals(x,y) returns true if and only if x and y refer to the same object.If x and y both do not refer to any object, then clearly they do not refer to the same object, because neither refers to an object in the first place. The correct way to characterize the behaviour of reference equality is
Object.ReferenceEquals(x,y) returns true if and only if either x and y refer to the same object, or x and y are both null references.
***********
(*) And yet I am a fan of the "null object pattern". Life is just full of these little contradictions.
[Eric is on vacation this week; this posting is pre-recorded.]
Comments
Anonymous
October 29, 2009
as usual, great example (and funny too) to illustrate a point.Anonymous
October 29, 2009
The comment has been removedAnonymous
October 29, 2009
that was a fun to read, thanksAnonymous
October 29, 2009
Analysis like this is why you belong in language development. Most impressive. It's amazing how straightforward this stuff is when you take the time to logic it out.Anonymous
October 29, 2009
Interesting !!!! its been a while from language world --- aricles like these create interest to researchAnonymous
October 29, 2009
The comment has been removedAnonymous
October 29, 2009
You could easily define that by 'null and x refer to the same object' you mean 'x is null'. This might not be intuitively obvious, but then at least the relation 'refer to the same object' is defined over all references, which is mathematically pleasing, like closure is for operators.Anonymous
October 29, 2009
@keith True they would not be the same, but neither would they be Eric's Ford Focus and Leah's Ford Focus. Since Eric and Leah own no Foci those are both null. But The Ford Focus Considered By Eric and The Ford Focus Considered By Leah are not null: they have real and different referents and hence are neither null nor equal. In SQL terms you are following the Considered relationship rather than the Owns relationship between Persons and Ford Foci. Or, more brutally, your query is: "SELECT * FROM FORD_FOCI WHERE ID IN (SELECT CONSIDERED FROM PERSONS WHERE NAME LIKE "ERIC");" instead of "SELECT * FROM FORD_FOCI WHERE ID IN (SELECT OWNS FROM PERSONS WHERE NAME LIKE "ERIC");". It's a rookie mistake - try to keep your focus.Anonymous
October 29, 2009
Oh well, just a moment ago I've got to know what a billion-dollar mistake is, and now there's your story =)Anonymous
October 29, 2009
>> Since we were married when she bought the car, and we continue to be married, what's mine is hers and what's hers is mine Prior to getting married my father had a slightly different spin on this. He said: "What's your's is her's and what is her's is her's." -MikeAnonymous
October 29, 2009
Hi Eric, Since you are a fan of the null object pattern why did you (your team) not implement it with events in c#. I often wish it was the default implementation. I would like that too, but there are a few reasons to not do so. First off, doing so complicates initialization; it is a nice fact that initializing all memory associated with a new object to zeros gives default semantics; if the memory manager had to figure out what object reference to put into an event field, that would complicate the memory manager. I suppose we could have done it in the compiler to generate the initialization in the construction sequence. We could ensure that the field is never accessed before it is initialized. But then what to do for structs with events? Structs do not have a default constructor. And a nice thing about structs is that allocating and deallocating them is very cheap if they can stay on the stack; the singleton delegate would have to be allocated on the heap. It's a nice property of structs that you can often use them in a manner that guarantees that they do not impose load on the garbage collector; this design choice would take away that ability from all users who want to have structs with events. In short, it's easy enough for you to use this pattern yourself if you want to take on its costs in exchange for its benefits. It's hard to say whether the increased flexibility of being able to do it both ways "pays for" the increase in potential for people doing it wrong. These things are judgment calls; that's what makes language design so interesting. -- EricAnonymous
October 29, 2009
I've always considered "null" to be a singleton object and therefore (inside my brain) your second statement is redundant.Anonymous
October 30, 2009
The comment has been removedAnonymous
October 30, 2009
@Pavel "In SQL, NULL really means 'unknown'" If we're splitting haris (and why else are any of us here, really), null semantics are pretty close to meaning "unknown" when considered at row scope. The aggregate operators often ignore nulls, though. To me, that doesn't fit the metaphor. 2 + 2 + null = null Sum({2, 2, null}) = 4 [not SQL notation, obviously] With null semantics, i's not clear to that anything "really means" anything. At best it is "really easier to understand" if you remember a certain few patterns and the scopes in which they apply.Anonymous
November 03, 2009
@Pavel, @keith, @Eric, @and the rest, So what on Earth does the NULL mean: unknown or non-existent? The example in the post itself (about the Ford Focus that was never bought) obviously points at the latter, but the comments about the SQL NULL seem to speak in favour of the former... Also, from my practical experience with Assembler and C/C++ on "good old" (well, certainly old!) MS-DOS, the NULL pointer means, "can be anything - a random memory address (but set to zero by most implementations) - do not touch!" That's more like "unknown", but that's if you regard a NULL pointer as a memory address. If you wax all object-oriented and see it as an un-initialized reference to an object, whatever that object is, then the meaning is, "you don't know what's on 'the other side', but you know what isn't there: there is almost certainly no object you are looking for, so don't delude yourself by assuming there is one". This is still mostly about unknown, but has a tinge of non-existence to it, too. And from here, the SQL people seem to move in the direction of the "unknown", and the C#/.NET people say it's "non-existent" - the Great Void, which is the same for all non-existent objects (so that Object.ReferenceEquals(x,y) returns true if both x and y are set to null)... Good fun, that. Ignoti et quasi occulti... :-)Anonymous
November 03, 2009
Sorry, everyone: I've typed up some nonsense above. I totally confused an uninitialized and un-allocated memory in MS-DOS and a pointer set to NULL. The latter may not have always been set to 0000:0000 (what if you switch to the protected mode, for example?), but it was always a definite value, not an unknown address. My memory must be going... :-) But my main question still stands: what is NULL now? Does it mean "unknown" or "non-existent?"Anonymous
November 04, 2009
How often do you see structs with events in them? I can't think of an instance where that is called for, but there may be some significant use case I'm not taking into account.Anonymous
May 27, 2010
The comment has been removedAnonymous
November 24, 2012
The comment has been removed