为啥 is 运算符在给定 null 时返回 false?
Posted
技术标签:
【中文标题】为啥 is 运算符在给定 null 时返回 false?【英文标题】:Why does the is operator return false when given null?为什么 is 运算符在给定 null 时返回 false? 【发布时间】:2011-11-30 04:50:27 【问题描述】:在我看来is
运算符有点不一致。
bool Test()
// Returns false, but should return true.
return null is string;
人们期望null
值属于任何引用(或可为空)类型。事实上,C# 语言规范中的某些内容支持这一假设,例如(6.1.6 隐式引用转换):
隐式引用转换是: ... • 从空文字到任何引用类型。
is
运算符的描述(7.10.10 is 运算符)首先说,当存在从 E
到 T
的引用转换时,表达式 (E is T)
将导致 true,但随后作者继续明确排除 E
是 null
文字或具有 null
值的情况。
他们为什么这样做?在我看来,这似乎违反直觉。
【问题讨论】:
为什么他们明确排除 null 充其量是程序员的一个问题。***.com 我无法撤销我的近距离投票,但这些问题在这里很好:meta.stackexchange.com/questions/36850/… 在java中null typeof Object
也返回false
假设null is string
是true
,这意味着null
是string
。还假设null is Nullable<int>
是true
,这意味着null
是Nullable<int>
。现在,回答这个问题:null
是什么类型的?
@Michael Kjörling:不合逻辑。从上述事实(null 是一个字符串,null 是一个 Nullable这个问题是subject of my blog on May 30th 2013。谢谢你的好问题!
你正盯着一条空荡荡的车道。
有人问你“你的车道能停一辆本田思域吗?”
是的。可以。
有人将您指向第二条车道。它也是空的。他们问“我车道上的当前内容是否适合您的车道?”
是的,很明显。两条车道都是空的!很明显,一个的内容可以适合另一个,因为首先没有任何一个的内容。
有人问你“你的车道上有本田思域吗?”
不,它没有。
您认为is
运算符回答了第二个问题:给定这个值,它是否适合该类型的变量? 空引用是否适合这种类型的变量?是的。
这不是is
操作员回答的问题。 is
操作员回答的问题是第三个问题。 y is X
不问“y
是 X
类型变量的合法值吗?”它问“y
是对 @ 类型对象的有效引用吗?” 987654333@?" 由于空引用不是对 any 类型的 any 对象的有效引用,因此答案为“否”。那条车道是空的;它不包含本田思域。
另一种看待它的方式是y is X
回答了“如果我说y as X
,我会得到非空结果吗?如果 y 为空,显然答案是否定的!
更深入地了解您的问题:
人们期望空值属于任何引用(或可为空)类型
人们会隐含地假设一个类型是一个值的集合,并且值y与一个变量的赋值兼容性类型 X 无非是检查 y 是否是集合 x 的成员。
虽然这是查看类型的一种极其常见的方式,但这并不是查看类型的唯一方式,也不是 C# 查看类型的方式。空引用是 C# 中无类型的成员; 赋值兼容性 不只是检查一个集合以查看它是否包含一个值。仅仅因为 null 引用与引用类型 X 的变量赋值兼容并不意味着 null 是 X 类型的成员。“赋值兼容”关系和“是类型的成员” " 关系显然有很多重叠,但在 CLR 中它们并不完全相同。
如果您对类型理论感兴趣,请查看我最近关于该主题的文章:
What is this thing you call a "type"? Part one
What is this thing you call a "type"? Part Two
【讨论】:
@Gebb:很高兴为您提供帮助。您可能也会对这篇文章感兴趣:blogs.msdn.com/b/ericlippert/archive/2010/09/16/… Eric 把它变成了一篇博文:ericlippert.com/2013/05/30/what-the-meaning-of-is-isy is X
不问“y
是X
类型变量的合法值吗?”它询问“y
是对X
类型对象的有效引用吗?”这就是重点!谢谢!
但如果我问y is int?
,那么我会问“你的车道上是本田思域还是什么都没有?”。当您的车道空无一人时,为什么答案仍然是否定的?如果您深入了解情况,情况只会变得更糟,因为问题变成了“您的车道上是否有本田思域或标有‘这里没有本田思域’的标志?”。即使您的车道上有上述标志,答案仍然是否定的。
阅读本文时,我感受到了公主新娘的气息。 “显然我不能选择我面前的酒!”【参考方案2】:
我认为null is string
返回 false 非常直观。 Null 没有任何意义,它绝对不是字符串。所以它应该返回false。虽然这是语言设计者做出的选择,但当您考虑 null 的实际含义时,它是一个非常直观的选择。
【讨论】:
+1 因为问题实际上是关于它是否直观而不是质疑OP已经知道的规范。如果你用英文句子“isnull
a string”问它,答案是否定的,不是,这与“is null
assignable to string
”不同
null is string
非常直观,(string)null is string
如果您对 C# 中空引用的工作方式不是很熟悉,可能需要暂停一下。【参考方案3】:
null
文字可以分配给 any 引用类型。它本身不是一种类型。它是一个特殊的literal,表示一个空引用。
如果is
将在传入null
时返回true
,那么您可以使用null
文字做什么?没什么 - 它是null
。除了令人困惑的事情之外,它返回true
有什么意义?
不管 - 就直观而言,阅读英文代码并告诉我:
null is string;
当我看到它时,它似乎在问问题is "nothing" a string?
。我的直觉告诉我,不,不是——它是nothing
。
【讨论】:
没关系,但它也是一个字符串,对吧?但是为什么(null is string)
会返回flase 呢?
我会反过来说。任何引用类型都可以为空。 null 只是 null。
@Oded 那么空值是对象类型的有效值吗?我可以将它分配给这种类型的变量,对吧?所以答案似乎是肯定的,这个值是完全有效的,我的猜测是(null is object)
表达式应该准确地检查这一点。
@Gebb:不要忘记 ValueTypes 也是对象,但不是引用类型。
@Oded:“除了令人困惑的事情之外,它返回 true 的意义何在?”实际上,它会使语言更合乎逻辑。考虑这两点:(1)is
操作符检查是否存在引用(我们这里不需要其他类型的转换)转换; (2)null
可以转换为任何引用类型。因此(null is T)
,其中 T 是引用类型应该返回 true。但是不,这里我们有一个明确的例外,这让我感到困惑。【参考方案4】:
http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx
如果满足以下两个条件,则 is 表达式的计算结果为 true 满足:
表达式不为空。 表达式可以转换为类型。也就是说, form (type (expression) 将在不引发异常的情况下完成。 有关详细信息,请参阅 7.6.6 转换表达式。
【讨论】:
无论如何文档只说明表达式不能为空(我们已经知道),但它没有说明原因 你为什么要其他方式? @username:这个答案解释了它的机械工作方式,并引用了一个参考资料,它为您提供了一个可以使用的模型。你在这里问宇宙的意义。我想你很幸运,我们的上帝经常光顾;)【参考方案5】:实际上,“null is T == false”可以节省我输入额外的代码:
不用说
if (X != null && X is Foo)
我只能说
if (X is Foo)
并完成它。
【讨论】:
【参考方案6】:
null
值
我从您的问题中引用了这一点,因为它似乎触及了问题的核心。 null
不是一个值 - 它是一个值的缺失。 is
对我来说似乎是为了回答这个问题:
如果我将
E
转换为T
,我会成功获得T
吗?
现在,虽然您可以将null
转换为T
没有错误,但在这样做之后,您不要“有一个T
" - 你仍然一无所有。所以null
不是“是”T
,所以is
返回false。
【讨论】:
【参考方案7】:在 Java 中,有一个操作符可以做完全相同的事情,但它的名称要长得多:instanceof
。 null instanceof String
返回 false 非常直观,因为 null 不是任何事物的实例,更不用说 String
。因此,当使用null
时,Java 的版本更直观一些。
但是,当要求查看整个层次结构时,这两个运算符都会返回 true。例如。如果String
的实例是Object
。这里是 Java 不太直观(因为一个实例实际上有一个非常特定的类型),而 C# 的 is
更直观(因为每个String
是一个Object
深处)。
底线:如果你试图用一个词来描述相当高级的逻辑,你肯定很少有人会这样或那样混淆。似乎大多数人都同意一个含义,而那些不同意的人则不得不调整。
【讨论】:
以上是关于为啥 is 运算符在给定 null 时返回 false?的主要内容,如果未能解决你的问题,请参考以下文章
为啥当@val IS NULL 时SELECT 'A' WHERE @val IN (1, 2, 3, NULL) 不返回值? [复制]
Python - 为啥在这种情况下“is”运算符返回 true? [复制]
为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function