ChatGPT解决这个技术问题 Extra ChatGPT

Why does the is operator return false when given null?

c#

It seems to me that the is operator is a bit inconsistent.

bool Test()
{
    // Returns false, but should return true.
    return null is string;
}

One expects that the null value belongs to any reference (or nullable) type. And indeed, the C# language specification says something which supports this hypothesis, for example (6.1.6 Implicit reference conversions):

The implicit reference conversions are: ... • From the null literal to any reference-type.

The description (7.10.10 The is operator) of the is operator starts by saying that the expression (E is T) will result in true when a reference conversion from E to T exists, but then the authors go on by explicitly excluding the case when E is the null literal or has a null value.

Why do they do that? To me it seems counterintuitive.

Why they explicitly excluded null is at best a question for programmers.stackoverflow.com
I can't rescind my close vote, but these questions are fine here: meta.stackexchange.com/questions/36850/…
in java null typeof Objectalso returns false
Assume that null is string were true, and this implied that null is a string. Also assume that null is Nullable<int> is true, implying that null is a Nullable<int>. Now, answer this question: of what type is null?
@Michael Kjörling: Non sequitur. From the mentioned facts (null is a string, null is a Nullable) it doesn't follow that I should be able to answer that question.

b
bjan

This question was the subject of my blog on May 30th 2013. Thanks for the great question!

You're staring at an empty driveway.

Someone asks you "can your driveway hold a Honda Civic?"

Yes. Yes it can.

Someone points you at a second driveway. It is also empty. They ask "Can the current contents of my driveway fit in your driveway?"

Yes, obviously. Both driveways are empty! So clearly the contents of one can fit in the other, because there are no contents of either in the first place.

Someone asks you "Does your driveway contain a Honda Civic?"

No, it does not.

You're thinking that the is operator answers the second question: given this value, does it fit in a variable of that type? Does a null reference fit into a variable of this type? Yes it does.

That is not the question that the is operator answers. The question that the is operator answers is the third question. y is X does not ask "is y a legal value of a variable of type X?" It asks "Is y a valid reference to an object of type X?" Since a null reference is not a valid reference to any object of any type, the answer is "no". That driveway is empty; it doesn't contain a Honda Civic.

Another way to look at it is that y is X answers the question "if I said y as X, would I get a non-null result? If y is null, clearly the answer is no!

To look a little deeper at your question:

One expects that the null value belongs to any reference (or nullable) type

One would be implicitly assuming that a type is a set of values, and that assignment compatibility of a value y with a variable of type X is nothing more nor less than checking whether y is a member of set x.

Though that is an extremely common way of looking at types, that is not the only way of looking at types, and it is not the way that C# looks at types. Null references are members of no type in C#; assignment compatibility is not merely checking a set to see if it contains a value. Just because a null reference is assignment compatible with a variable of reference type X does not mean that null is a member of type X. The "is assignment compatible with" relation and the "is a member of type" relation obviously have a lot of overlap, but they are not identical in the CLR.

If musings about type theory interest you, check out my recent articles on the subject:

What is this thing you call a "type"? Part one

What is this thing you call a "type"? Part Two


@Gebb: Glad to help. This article might also be of interest to you: blogs.msdn.com/b/ericlippert/archive/2010/09/16/…
Eric turned this into a blog post: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
y is X does not ask "is y a legal value of a variable of type X?" It asks "Is y a valid reference to an object of type X?" That was the whole point! thanks!
But if I ask y is int?, then I would be asking "Does your driveway contain a Honda Civic or nothing?". Why is the answer still no when your driveway is empty? If you look under the hood it only gets worse, as the question becomes "Does your driveway contain a Honda Civic or a sign that says 'No Honda Civic here'?". Even if your driveway contains said sign, the answer is still no.
While reading this I was getting Princess Bride vibes. "Clearly I cannot choose the wine in front of me!"
m
manojlds

I think null is string returning false is very intuitive. Null means nothing, and it is definitely not a string. So it should return false. While it is a choice the language designers made, it is a very intuitive one when you consider the real world meaning of null.


+1 because the question is really about whether it's intuitive and not questioning the spec, which the OP is already aware of. If you ask it as an English sentence "is null a string" the answer is no, it is not, which is different from "is null assignable to string"
null is string is pretty intuitive, (string)null is string might require a pause if you're not really familiar with how a null reference works in C#.
O
Oded

The null literal can be assigned to any reference type. It is not a type in an of itself. It is a special literal that represents a null reference.

In the case that is would return true when a null would be passed in, what would you be able to do with the null literal? Nothing - it is null. What would be the point of it returning true except for confusing matters?

Regardless - in terms of how intuitive that is, read the code in English and tell me:

null is string;

When I see that, it seems to be asking the question is "nothing" a string?. My intuition tells me that no, it isn't - it's nothing.


That's ok, but then it is also a string, right? But why does (null is string) return flase then?
I would've phrased it the other way round. Any reference type can be null. null is just null.
@Oded so is the null value a valid value of, say, the object type? I can assign it to a variable of this type, right? So the answer seems to be yes, the value is perfectly valid, and my guess is that the (null is object) expression should check exactly that.
@Gebb: Don't forget that ValueTypes are also objects, but not reference types.
@Oded: "What would be the point of it returning true except for confusing matters?" Actually, it would make the language more logical. Consider these two points: (1) the is operator checks if a reference (we don't need other types of conversion here) conversion exists; (2) null can be converted to any reference type. Therefore (null is T), where T is a reference type should return true. But no, here we have that explicit exception, which is what seems confusing to me.
S
Svish

http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx

An is expression evaluates to true if both of the following conditions are met: expression is not null. expression can be cast to type. That is, a cast expression of the form (type (expression) will complete without throwing an exception. For more information, see 7.6.6 Cast expressions.


Anyway the documentation only states that expression cannot be null (that we already know), but it doesn't tell why
Why would you want it any other way?
@username: This answer explains the way it works mechanically, and cites a reference, which gives you a model to work with. You're asking the meaning of the universe here. I guess you're lucky that our god frequents SO ;)
R
Rodger Vance

As a practical matter, having "null is T == false" saves me typing extra code:

Instead of having to say

if (X != null && X is Foo) {}

I can just say

if (X is Foo) {}

and be done with it.


A
AakashM

the null value

I've quoted this from your question because it seems to get to the heart of the matter. null isn't a value - it's the absence of a value. The purpose of is to me seems to be to answer the question:

If I cast E to T, will I successfully get a T ?

Now, while you can cast null to T without error, after doing so you don't "have a T" - you've still got nothing. So it's not the case that null "is" a T, so is returns false.


A
Agent_L

In Java there is an operator that does exactly same thing, but it has much longer name: instanceof. It's very intuitive there that null instanceof String returns false, because null is not an instance of anything, much less a String. So, when using null the Java's version is bit more intuitive.

However, both of those operators return true when asked to look through entire hierarchy as well. Eg. if instance of String is an Object. And here it's Java that's bit less intuitive (because an instance actually has one, very specific type) and C#'s is is more intuitive (because every String is an Object deep inside).

Bottom line: if you try to describe pretty advanced logic in one word, you're bound to have few people confused, this way or another. It seems that most people agreed on one meaning and those who did not agree, had to adjust.