繁体   English   中英

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

[英]Why does the is operator return false when given null?

在我看来, 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)将导致真正的当从引用转换ET存在,但随后笔者通过明确排除的情况下继续当Enull文字或具有null值时。

他们为什么这样做? 这对我来说似乎违反直觉。

这个问题是我2013年5月30日博客主题 谢谢你这个好问题!


你正盯着一条空车道。

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

是。 是的,它可以。

有人指着你在第二个车道。 它也是空的。 他们问:“我的车道的当前内容能否适合您的车道?”

是的,很明显。 两条车道都是空的! 很明显,一个人的内容可以适合另一个,因为首先没有任何内容。

有人问你“你的车道是否包含一辆本田思域?”

不,不是的。

您认为is运算符回答了第二个问题: 给定此值,它是否适合该类型的变量? null引用是否适合此类型的变量? 是的,它确实。

这不是问题的is运营商的答案。 现在的问题是, is运营商的答案是第三个问题。 y is X不问“ y类型的变量的合法值X ?”这问“ y至类型的对象的有效引用X ?”由于空引用不是任何 任何对象的有效引用类型,答案是“不”。 那条车道是空的; 它不包含本田思域。

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


要更深入地了解您的问题:

一个人期望null值属于任何引用(或可空)类型

可以隐含地假设类型是一组值 ,并且值y与类型X的变量的赋值兼容性仅仅是检查y是否是集合x的成员

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

如果关于类型理论的思考对你感兴趣,请查看我最近关于这个主题的文章:

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

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

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

在这种情况下is将返回truenull将被传递中,你将能够用做null的文字? 没什么 - 它是null 除了令人困惑的事情之外,它会回归true的重点是什么?


无论如何 - 就直观性而言,请阅读英文代码并告诉我:

null is string;

当我看到它时,它似乎在问这个问题is "nothing" a string? 我的直觉告诉我,不,它不是 - 它nothing

我认为null is string返回false是非常直观的。 Null意味着什么,它绝对不是一个字符串。 所以它应该返回false。 虽然它是语言设计者的选择,但当你考虑null的真实世界意义时,它是一个非常直观的选择。

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

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

  • 表达式不为空。
  • 表达式可以转换为类型。 也就是说,表单的类型(表达式)将在不抛出异常的情况下完成。有关更多信息,请参阅7.6.6 Cast表达式。

实际上,“null是T == false”可以节省我输入额外的代码:

而不是说

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

我可以说

if (X is Foo) {}

并完成它。

null

我从你的问题中引用了这个,因为它似乎触及了问题的核心。 null 不是值 - 它是缺少值。 的目的is对我似乎是回答这个问题:

如果我把E投到T ,我会成功获得T吗?

现在,虽然你可以毫无错误地将nullT 这样做之后你就不会 “有一个T ” - 你仍然没有任何东西。 所以它不是的情况下null “是” T ,所以is返回false。

在Java中,有一个运算符执行完全相同的操作,但它具有更长的名称: instanceof 在那里, null instanceof String返回false是非常直观的,因为null不是任何东西的实例,更不是String 因此,当使用null ,Java的版本更直观一些。

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

一句话:如果你试图用一个词来描述非常高级的逻辑,那么你很少会有这样或那样的人混淆。 似乎大多数人都同意一个意思而那些不同意的人不得不进行调整。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM