Today a follow-up to my 2010 article about the meaning of the
is operator. Presented as a dialog, as is my wont!
I've noticed that the
isoperator is inconsistent in C#. Check this out:
string s = null; // Clearly null is a legal value of type string bool b = s is string; // But b is false!
What's up with that?
Let's suppose you and I are neighbours.
Um... ok, I'm not sure where this is going, but sure.
I'm looking into your driveway, which is empty. Can that driveway hold a Honda Civic?
Sure, no problem. In fact, it frequently does.
Now we cross the street and we look at my driveway, which is also empty. Can it hold a Honda Civic?
Yes, I suppose so.
In fact I have a rule that only Honda Civics may be parked in my driveway.
That's a bit weird, but that's your business.
Can the present contents of my driveway be placed in your driveway?
Um... I don't know. That's a strange question. On the one hand I want to say that the question presupposes a false premise, namely that "the present contents of my empty driveway" refers to an object that can be moved from one place to another. On the other hand, the contents of our two empty driveways seem to be by definition "the same", namely, "zero Honda Civics". If you insist on an answer then I suppose I will have to say yes, the present contents of your driveway fit into my driveway.
OK, so, does your driveway contain a Honda Civic?
Obviously not. It's empty.
Well, aren't you being inconsistent then? Let's review the facts.
- You agree that my driveway only contains Honda Civics.
- You agree that the present contents of my driveway are identical to the contents of your driveway.
- And yet you conclude that your driveway does not contain a Honda Civic!
Either you are being inconsistent or there is something wrong with this logic.
I'd agree with that! There's something wrong with your logic.
And now we see why the
is operator is actually consistent. The fact that a null reference may be assigned to a string variable does not make the null reference a string, any more than the fact that your driveway can be empty means that an empty driveway contains a Honda Civic. The
is operator does not answer the question "can I assign this reference to a variable of the given type?" It answers the question "is this reference a legitimate reference to an object of the given type?", and null is not a legitimate reference.
I'm beginning to see your point, but actually I never believed that the operator was answering a question about assignment compatibility. I believed that the operator was answering a question about type membership. Surely the null reference is a member of the string type!
Someone once told me that the fastest way to spot the weak point in an argument is to look for the "surely".
Actually, no. A common conception of types is that a type is a set, possibly infinite, of values, and that assignment compatibility is merely checking to see if a given value is a member of the necessary set. But that's not the case in C#. The null reference actually is not assigned any type at all; it is explicitly of no type, but it is assignment compatible with a variable of any reference type.1 The assignment compatibility relationship and the type membership relationship are similar in a lot of ways but they are not identical.
Finally I know what the true meaning of what
Awesome! Alert Bill Clinton!
Next time on FAIC: An interesting integer identity.
- In C# 1.0 and 2.0 the specifications said that the null reference was the sole member of a special "null type", but this concept turned out to not be fruitful. You can't declare a variable of the null type, you can't use the null type as a generic type argument, basically it's a type that you can't actually use as a type. Mads deleted that concept from the C# 3.0 spec because it simply was not useful and caused more confusion than it prevented. ↩