首页 文章

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

提问于
浏览
120

在我看来, is 运算符有点不一致 .

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

人们期望 null 值属于任何引用(或可空)类型 . 事实上,C#语言规范说明了支持这种假设的东西,例如(6.1.6隐式引用转换):

隐式引用转换是:...•从null文本到任何引用类型 .

is 运算符的描述(7.10.10 is运算符)首先表示当从 ET 的引用转换存在时,表达式 (E is T) 将导致为true,但是当 EE 时,作者继续明确排除该情况 null literal或具有 null 值 .

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

7 回答

  • 2

    这个问题是subject of my blog on May 30th 2013 . 谢谢你这个好问题!


    你正盯着一条空车道 .

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

    是 . 是的,它可以 .

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

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

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

    不,不是的 .

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

    这不是 is 运营商回答的问题 . is 运算符回答的问题是第三个问题 . y is X 不询问“是 y _1188053_类型的变量的合法值?" It asks "是 yX 类型的对象的有效引用?”由于空引用不是对任何类型的任何对象的有效引用,因此答案是"no" . 那条车道是空的;它不包含本田思域 .

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


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

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

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

    虽然这是查看类型的一种非常常见的方式,但这不是查看类型的唯一方法,而且它不是C#查看类型的方式 . 空引用是C#中没有类型的成员;赋值兼容性不仅仅是检查一个集合以查看它是否包含值 . 仅仅因为null引用是与引用类型X的变量兼容的赋值并不意味着null是X类型的成员."is assignment compatible with"关系和"is a member of type"关系显然有很多重叠,但它们在CLR中不相同 .

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

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

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

  • 23

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

    如果 is 将在传入 null 时返回 true ,您可以用 null 文字做什么?没什么 - 它是 null . 除了令人困惑的事情之外,它返回_1588070会有什么意义?


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

    null is string;
    

    当我看到它时,它似乎在问问题 is "nothing" a string? . 我的直觉告诉我,不,它不是't - it' s nothing .

  • 9

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

  • 10

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

    如果满足以下两个条件,则表达式求值为true:expression不为null . 表达式可以转换为类型 . 也就是说,形式(类型(表达式)的强制转换表达式将完成而不会抛出异常 . 更多信息,请参见7.6.6转换表达式 .

  • 21

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

    而不是说

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

    我可以说

    if (X is Foo) {}
    

    并完成它 .

  • 6

    空值

    我从你的问题中引用了这个,因为它似乎触及了问题的核心 . null 不是一个值 - 它没有值 . is 给我的目的似乎是回答这个问题:

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

    现在,虽然你可以毫无错误地将 null 转换为 T ,但这样做之后你不会“拥有 T ” - 你've still got nothing. So it' "is"不是've still got nothing. So it',所以 is 返回false .

  • 178

    在Java中,有一个运算符完全相同,但它有更长的名称: instanceof . 这是非常直观的 null instanceof String 返回false,因为null不是任何事物的实例,更不用说 String . 因此,当使用 null 时,Java的版本更直观一些 .

    但是,当要求查看整个层次结构时,这两个运算符都返回true . 例如 . 如果 String 的实例是 Object . 而且这里's Java that'有点不那么直观(因为一个实例实际上有一个非常特定的类型)而且C#的 is 更直观(因为每个 String is 内部都是 Object ) .

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

相关问题