在我看来,is操作符有点不一致。
1 2 3 4 5
| bool Test ()
{
// Returns false, but should return true.
return null is string;
} |
我们期望null值属于任何引用(或可以为空)类型。实际上,C语言规范说明了一些支持这个假设的东西,例如(6.1.6隐式引用转换):
The implicit reference conversions are:
...
? From the null literal to any reference-type.
is运算符的描述(7.10.10 is operator)开始时说,当存在从E到T的引用转换时,表达式(E is T)将导致true,但作者继续明确排除当E是null文本或具有null值时的情况。UE。
他们为什么这么做?在我看来,这是违反直觉的。
- 我们可能需要埃里克·利珀特。
- @aakashm:编辑。添加了规范的准确部分。
- @GEBB谢谢,回答了你的实际问题,我想,既然我读得很好:)
- 对于programmers.stackoverflow.com来说,为什么它们显式地排除了空值充其量是一个问题。
- 我不能取消我的近距离投票,但这些问题在这里很好:meta.stackexchange.com/questions/36850/…
- 在Java EDCOX1中,0个词也返回false
- 假设null is string是true,这意味着null是string。同时假设null is Nullable为true,即null为Nullable。现在,回答这个问题:null是什么类型的?
- @迈克尔·凯吉&246;林:非理性。从上面提到的事实(空是一个字符串,空是一个可以为空的)来看,我不能回答这个问题。
- @格布,没错。如果你说null is (somenullabletype) == true,那么它也意味着null is (someunrelatednullabletype) == true,因为null对于这两种类型的变量都是有效的状态。因此,null将是这两种不相关的类型。
- @迈克尔:但这不是问题。在引入上下文之前,literal 2.0也可以是多个类型。
- @艾蒂安·埃德马特尔:在你发表评论后的39分29秒,一切都完成了…做得好:P
- 一个杯子可以是空的,但空不是一个杯子。
这个问题是我2013年5月30日博客的主题。谢谢你的提问!
你盯着一条空车道。
有人问你,"你的车道能容纳本田思域吗?"
对。是的,可以。
有人指着第二条车道。它也是空的。他们问"我车道上的当前内容是否适合您的车道?"
是的,很明显。两条车道都是空的!所以很明显,其中一个的内容可以与另一个相匹配,因为一开始都没有任何内容。
有人问你"你的车道上有本田思域吗?"
不,不是。
您认为is运算符回答了第二个问题:给定这个值,它是否适合该类型的变量?空引用是否适合此类型的变量?是的。
这不是is操作员回答的问题。is操作员回答的问题是第三个问题。y is X没有问"y是X型变量的合法值吗?"它问"y是否是对X类型对象的有效引用?"由于空引用不是对任何类型对象的有效引用,因此答案是"否"。那条车道是空的,里面没有本田思域。
另一种看问题的方法是,y is X回答问题"如果我说y as X,我会得到一个非空的结果吗?如果y为空,则显然答案为否!
要深入了解您的问题:
One expects that the null value belongs to any reference (or nullable) type
我们可以隐式地假设一个类型是一组值,并且值y与类型x的变量的赋值兼容性仅限于检查y是否是集x的成员。
虽然这是查看类型的一种非常常见的方法,但这不是查看类型的唯一方法,也不是C_查看类型的方法。空引用是C赋值中没有类型的成员,兼容性不仅仅是检查集合是否包含值。仅仅因为空引用的赋值与引用类型x的变量兼容并不意味着空是类型x的成员。"is assignment compatible with"relation和"is a member of type"relation显然有很多重叠,但它们在clr中并不相同。
如果你对类型理论感兴趣,请看我最近关于这个主题的文章:
你所说的"类型"是什么?第一部分
你所说的"类型"是什么?第二部分
- 你答案的第二部分真的向我解释了这一点。谢谢您。
- @格布:很乐意帮忙。这篇文章也可能引起您的兴趣:blogs.msdn.com/b/ericlippet/archive/2010/09/16/…
- 埃里克把这变成了一篇博文:ericlippert.com/2013/05/30/what-the-meansion-of-is-is
- @凯文斯卡特:谢谢,我忘了在这里更新链接。
- 车的不错选择,+1
- y is X没有问"y是X型变量的合法值吗?"它问"y是对X类型对象的有效引用吗?"这就是重点!谢谢!
- 但如果我问y is int?,我会问"你的车道上有本田思域车吗?"为什么你的车道是空的时候答案仍然是否定的?如果你看看引擎盖下面,情况就更糟了,因为问题变成了"你的车道上有本田思域还是有一个写着‘这里没有本田思域’的标志?"即使你的车道上有这样的标志,答案仍然是否定的。
- is回答(y as X) != null是否真的足够了。
- @杰拉德:当我给出冗长、冗长、健谈的答案时,人们会告诉我它们应该更短,而当我给出简洁、简洁的答案时,人们会告诉我它们应该更长。我的结论是:人们喜欢抱怨。既然你对这个八年前的问题有一个很好的答案,我的建议是,你自己回答,让我们知道什么是好的答案,这样我们才能学习。
可以将null字面值分配给任何引用类型。它本身不是一个类型。它是表示空引用的特殊文本。
如果is会返回true,那么当null会被传入时,您将如何处理null文本?什么都没有-它是null。它返回true有什么意义,除了混乱的事情?
不管怎样-从直观的角度来看,用英语阅读代码并告诉我:
当我看到这一点时,似乎是在问一个问题。我的直觉告诉我,不,不是-是nothing。
- 没关系,但它也是一根绳子,对吧?但是为什么(null is string)会返回Flase呢?
- @你可能是指一根绳子。或者一个Object。或者一个StringBuilder。或者…
- 我本可以换个说法。任何引用类型都不能为空。空就是空。
- @因此,空值是对象类型的有效值吗?我可以把它赋给这种类型的变量,对吗?因此,答案似乎是肯定的,这个值是完全有效的,我的猜测是,(null is object)表达式应该检查这一点。
- @GEBB:不要忘记,值类型也是对象,但不是引用类型。
- string blah = null; Console.WriteLine(blah is string);将打印False。为什么?见Hemal Pandya的回答
- @奥德:"除了令人费解的事情之外,它回归真实的意义是什么?"事实上,这会使语言更加合乎逻辑。考虑这两点:(1)is运算符检查是否存在引用(此处不需要其他类型的转换)转换;(2)null是否可以转换为任何引用类型。因此,当t是引用类型时,(null is T)应该返回true。但不,这里我们有一个明确的例外,这让我感到困惑。
- 这里的关键是,正如@oded指出的那样:"它回归真实的意义是什么?"
我认为null is string返回错误是非常直观的。空意味着什么都没有,它绝对不是字符串。所以应该返回false。虽然这是语言设计者所做的选择,但当你考虑到"空"的真实含义时,这是一个非常直观的选择。
- +1因为问题实际上是关于它是否直观,而不是质疑操作人员已经知道的规范。如果你把它作为一个英语句子问"is nulla string",答案是"no,it is not,which is different to"is nullassignable to string。
- null is string非常直观,如果您不太熟悉C中的空引用的工作方式,(string)null is string可能需要暂停。
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.
- +1用于链接到文档
- 无论如何,文档只声明表达式不能为空(我们已经知道了),但它不能说明原因。
- 你为什么要其他的方式?
- @用户名:这个答案解释了它的机械工作方式,并引用了一个引用,它为您提供了一个要使用的模型。你在问宇宙的意义。我想你很幸运我们的上帝经常这样出现;)
实际上,"null is t==false"可以节省我键入额外代码的时间:
而不是说
1
| if (X != null && X is Foo ) {} |
我只能说
完成它。
the null value
我从你的问题中引用了这句话,因为它似乎触及了问题的核心。null不是一个值,而是一个值的缺失。在我看来,is的目的似乎是回答这个问题:
If I cast E to T, will I successfully get a T ?
现在,虽然您可以毫无错误地将null强制转换为T,但这样做之后,您就没有"拥有T"—您仍然一无所获。所以不是说null是"T",所以is返回错误。
在Java中有一个操作符做完全相同的事情,但是它有更长的名字:EDCOX1,0。很直观的是,null instanceof String返回false,因为null不是任何东西的实例,更不用说String。因此,当使用EDCOX1(3)时,Java的版本更直观。
但是,当被要求查看整个层次结构时,这两个操作符都返回true。例如,如果String的实例是Object。这里的Java有点不直观(因为一个实例实际上有一个,非常特定的类型),而C的EDCOX1(6)更直观(因为每一个EDCOX1 2)都是一个EDCOX1,5英寸深。
底线:如果你试图用一个词来描述相当高级的逻辑,你肯定会有很少的人困惑,不管是这样还是那样。似乎大多数人都同意一个意思,而那些不同意的人则不得不做出调整。