为什么在给定null时is运算符会返回false?


135

在我看来,is操作员有点不一致。

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

人们期望该null值属于任何引用(或可为空)类型。确实,C#语言规范说了一些支持此假设的内容,例如(6.1.6隐式引用转换):

隐式引用转换为:
...
•从null文字到任何引用类型。

对运算符的描述(7.10.10是is运算符)is首先说,(E is T)当存在从Eto 的引用转换时,表达式将为true T,但随后作者继续明确排除when Enull文字或具有null值的情况。 。

他们为什么这样做?在我看来,这违反直觉。


为什么他们明确排除在外空是最好的programmers.stackoverflow.com一个问题
惨变

2
我无法取消亲密的投票,但是这些问题在这里很好:meta.stackexchange.com/questions/36850/…–
Merlyn Morgan-Graham

在Java中null typeof Object也返回false
棘轮怪胎

假设null is stringtrue,这意味着这null是一个string。还假设null is Nullable<int>true,这意味着nullNullable<int>。现在,回答这个问题:什么是类型null
的CVn

1
@MichaelKjörling:不公开。根据提到的事实(null是一个字符串,null是一个Nullable <int>),并不意味着我应该能够回答这个问题。
Gebb 2011年

Answers:


195

这个问题是我2013年5月30日的博客主题。感谢您提出的好问题!


您盯着空车道。

有人问你“你的车道可以装一辆本田思域吗?”

是。是的,它可以。

有人将您指向第二条车道。它也是空的。他们问:“我的车道当前内容是否适合您的车道?”

是的,显然。两个车道都是空的!显然,其中一个的内容可以适合另一个,因为其中任何一个都不存在。

有人问您“您的车道上有本田思域吗?”

不,不是的。

您以为is操作员会回答第二个问题:给定该值,它是否适合该类型的变量? 空引用是否适合此类型的变量?是的,它确实。

那不是is操作员回答的问题。该问题is话务员应答是第三个问题。y is X不问“ y类型的变量的法律价值X ”它要求“ y对类型的对象的有效引用X ”由于空引用是不是一个有效的参考任何对象的任何类型,答案是“否”。那条车道是空的。它不包含本田思域。

另一种看待y is X问题的方法是回答问题“如果我说y as X,我会得到非空结果吗?如果y为null,显然答案是否定的!


要更深入地研究您的问题:

人们期望null值属于任何引用(或可为null)类型

会隐式地假设类型是一组值,并且值y与类型X的变量的分配兼容性只不过是检查y是否是集合x的成员而已。

尽管这是查看类型的一种非常常见的方式,但这不是查看类型的唯一方法,也不是C#查看类型的方法。空引用是C#中无类型的成员;分配兼容性不是只检查一组,看它是否包含一个值。仅仅是因为空引用是与引用类型X的变量兼容的赋值,并不意味着空是类型X的成员。“与...兼容的分配关系”和“是类型的成员”关系显然具有很多重叠,但是在CLR中它们并不相同。

如果您对类型理论的困惑感兴趣,请查看我最近关于该主题的文章:

您称之为“类型”的东西是什么?第一部分

您称之为“类型”的东西是什么?第二部分


@Gebb:很乐意提供帮助。这篇文章也可能是你的兴趣:blogs.msdn.com/b/ericlippert/archive/2010/09/16/...
埃里克利珀

埃里克(Eric)将其转为博客文章:ericlippert.com/2013/05/30/what-the-意思-of
Kevin Cathcart

y is X不会问“ y类型变量的合法值X吗?” 它询问“是否y有效引用了类型的对象X?” 这就是重点!谢谢!
贾拉勒

但是,如果我问y is int?,那么我会问:“您的车道上是否装有本田思域?当您的车道为空时,为什么仍然没有答案?如果您在引擎盖下看,只会变得更糟,因为问题变成“您的车道上是否装有本田思域或标有'此处没有本田思域'的标志?”。即使您的车道上包含上述标志,答案仍为否。
传真

1
@杰拉德:当我给出冗长,冗长,健谈的答案时,人们告诉我应该短一些,而当我给出简洁明了的答案时,人们告诉我应该更长一些。我的结论是:人们喜欢抱怨。既然您对什么是对这个已有八年历史的问题的最佳答案有感触,我的建议是您亲自回答一下,向我们展示什么才是最佳答案,以便我们学习。
埃里克·利珀特

24

我认为null is string返回false是非常直观的。Null毫无意义,而且绝对不是字符串。因此它应该返回false。尽管这是语言设计师做出的选择,但考虑到null的真实含义,这是一种非常直观的选择。


2
+1是因为问题实际上是关于它是否直观而不是质疑OP已经意识到的规范。如果您将其作为英语句子“是null字符串”来询问,答案是否定的,不是,这与“ null可分配给string”不同
Davy8 2011年

null is string非常直观,(string)null is string如果您不太了解C#中的空引用如何工作,则可能需要暂停一下。
decPL 2015年

24

null文字可以被分配给任何引用类型。它本身不是一种类型。这是一个特殊的文字表示空引用。

如果在传入a时is返回,那么您将如何处理原义?没事-是的。除了令人困惑的事情,它返回的意义是什么?truenullnullnulltrue


无论如何-就其直观程度而言,请阅读英语代码并告诉我:

null is string;

当我看到那句话时,似乎在问一个问题is "nothing" a string?。我的直觉告诉我,不,不是-是nothing


可以,但是它也是一个字符串,对吗?但是,为什么(null is string)还要退回熔断呢?
Gebb 2011年

我会反过来说。任何引用类型都可以为null。null只是null。
Mark H

@Oded空值是对象类型的有效值吗?我可以将它分配给这种类型的变量,对吗?因此答案似乎是肯定的,该值是完全有效的,我的猜测是该(null is object)表达式应对此进行检查。
Gebb 2011年

@Gebb:不要忘记ValueTypes也是对象,但不是引用类型。
Mark H

1
@Oded:“除了令人困惑的事情之外,它返回true的意义何在?” 实际上,这将使该语言更具逻辑性。考虑以下两点:(1)is操作员检查是否存在引用(此处不需要其他类型的转换)转换;(2)null可以转换为任何引用类型。因此(null is T),在T是引用类型的情况下,应返回true。但是不,这里有一个明确的例外,这似乎让我感到困惑。
Gebb 2011年

12

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

如果同时满足以下两个条件,则is表达式的计算结果为true:

  • 表达式不为null。
  • 表达式可以强制转换为类型。也就是说,形式(类型(表达式))的转换表达式将完成而不会引发异常,有关更多信息,请参见7.6.6转换表达式。

1
无论如何,文档仅声明表达式不能为null(我们已经知道),但是并不能说明原因
用户名“

为什么还要其他方式呢?
可悲的变量

1
@username:此答案说明了它的机械工作方式,并引用了一个参考,为您提供了一个可以使用的模型。您在这里询问宇宙的含义。我想您很幸运,我们的上帝经常光顾;)
Merlyn Morgan-Graham

10

实际上,拥有“ null is T == false”可以省去我键入额外代码的麻烦:

不必说

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

我可以说

if (X is Foo) {}

并完成它。


8

null

我从您的问题中引用了此内容,因为它似乎已成为问题的核心。null 不是价值-缺少价值。is对我来说,目的似乎是要回答这个问题:

如果我投ET,将我顺利拿到T

现在,当你可以施放nullT 没有错误,这样做后,这样你就不会 “有T” -你仍然一无所获。因此,不是null“ is”是a T,因此is返回false。


3

在Java中有一个运营商所做的正是同样的事情,但它有更长的名字:instanceof。这很直观,它null instanceof String返回false,因为null不是任何实例,更不用说a了String。因此,使用nullJava版本时会更加直观。

但是,当要求他们查看整个层次结构时,这两个运算符都返回true。例如。如果的实例StringObject。在这里,它是Java中的不太直观(因为一个实例实际上有一个非常特殊类型)和C#的is是更直观的(因为每一个String 一个Object内心深处)。

底线:如果您试图用一个词来描述相当高级的逻辑,那么注定很少有人会这样或那样困惑。似乎大多数人都同意一种意思,而那些不同意的人不得不调整。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.