nullを指定するとis演算子がfalseを返すのはなぜですか?


135

ように私には思えるisオペレータはビット矛盾しています。

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

null値が任意の参照(またはnull許容)型に属していることを期待します。そして実際、C#言語仕様はこの仮説をサポートするものを示しています。例えば(6.1.6暗黙的な参照変換):

暗黙的な参照変換は次のとおり
です。...
•nullリテラルから任意の参照型へ。

演算子の説明(7.10.10 is演算子)は、からへの参照変換が存在する場合is、式(E is T)はtrueになると言いますが、作成者は、がリテラルまたは値を持つ場合を明示的に除外して続行します。ETEnullnull

なぜ彼らはそれをするのですか?私には直観に反するようです。


なぜ彼らは明示的に除外nullが最高の状態でprogrammers.stackoverflow.comについて質問です
惨めな変数

2
私は私の近くの投票を取り消すことはできませんが、これらの質問はここに罰金です: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ですか?
CVn、2011年

1
@MichaelKjörling:非Sequitur。言及された事実(nullは文字列、nullはNullable <int>)から、その質問に答えることができるはずではありません。
Gebb

回答:


195

この質問は、2013年5月30日の私のブログ主題でした。すばらしい質問をありがとう!


空の私道を見つめています。

「あなたの私道はホンダシビックを保持できますか?」

はい。はい、できます。

誰かがあなたを2番目の私道に向けます。また、それは空です。彼らは「私の私道の現在の内容があなたの私道に収まるか?」と尋ねます。

はい、明らかに。両方の私道は空です!そもそもどちらのコンテンツもないため、一方のコンテンツがもう一方のコンテンツに収まることは明らかです。

「あなたの私道にはホンダシビックが含まれていますか?」

いいえ、違います。

あなたはそれを考えています is演算子が2番目の質問に答えるこの値が与えられた場合、その型の変数に適合しますか? null参照はこの型の変数に適合しますか?はい、そうです。

それはisオペレーターが答える質問ではありません。疑問isオペレータが回答は3番目の質問です。y is X「聞いていないですy型の変数の有効な値X」それは尋ねる「ですy型のオブジェクトへの有効な参照X」はnull参照をへの有効な参照ではありませんので、任意ののオブジェクトの任意のタイプ、答えはノー」であります」その私道は空です。ホンダシビックは含まれていません。

それを見る別の方法は y is X「私が言った場合y as X、null以外の結果が得られますか?」という質問に答えることです。yがnullの場合、明らかに答えはノーです!


あなたの質問をもう少し深く見るには:

null値は任意の参照(またはnull可能)型に属していると予想されます

値のセットであり、値yと型Xの変数との代入互換性はそれ以下ではないと暗黙のうちに想定されます yがセットxのメンバーであるかどうかをチェックするされます。

これは型を見る非常に一般的な方法ですが、それだけが型を見る方法ではなく、C#が型を見る方法でもありません。null参照はC#では型のないメンバーです。割り当ての互換性はありません、セットに値が含まれているかどうかを確認するだけで。null参照が参照型Xの変数と代入互換性があるからといって、nullが型Xのメンバーであることを意味するわけではありません。「is代入互換性」関係と「is of member of type」関係には明らかに多くのオーバーラップしますが、CLRでは同じではありません。

型理論についての考察があなたに興味があるなら、この件に関する私の最近の記事をチェックしてください:

これを「タイプ」と呼ぶのは何ですか?パート1

これを「タイプ」と呼ぶのは何ですか?パート2


@Gebb:お役に立ててうれしいです。また、この記事では、あなたに興味があるかもしれません:blogs.msdn.com/b/ericlippert/archive/2010/09/16/...
エリックリペット

エリックはこれをブログ投稿に変えました:ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Kevin Cathcart

y is Xy型の変数の正当な値はありますXか?」「yタイプのオブジェクトへの有効な参照はありますXか?」それがすべてのポイントでした!ありがとう!
Jalal

しかし、私が尋ねるとy is int?、「あなたの私道にはホンダシビックが含まれていますか、何も含まれていませんか?」私道が空のとき、なぜ答えはまだいいえですか?ボンネットの下を見ると、「私道にはホンダシビックまたは「ここにホンダシビックはありません」という標識が含まれていますか?」という質問になるので、状況はさらに悪化します。あなたの私道に上記の標識が含まれていても、答えはまだノーです。
FAX

1
@ジェラード:私が長く、冗長で、おしゃべりな答えをするとき、人々は彼らがより短くなければならないと私に言う、そして私が簡潔な、簡潔な答えを与えるとき、彼らは彼らがより長くあるべきだと私に言う。私の結論は次のとおりです。人々は不平を言いたいです。この8年前の質問に対して何が良い答えを出すかについての気持ちがあるので、私が学べるように、自分で答えることによって何が良い答えを出すかを示してください。
Eric Lippert

24

null is stringfalseを返すのは非常に直感的だと思います。nullは何も意味せず、文字列ではありません。したがって、falseを返す必要があります。これは言語デザイナーが行った選択ですが、nullの実際の意味を考えると非常に直感的なものです。


2
+1は、OPがすでに認識している仕様を疑問視するのではなく、直感的であるかどうかについての質問です。あなたは英語の文としてそれを頼む場合「であるnullと異なっている答えは、それはないです、ないです、文字列」「であるnullに割り当て可能string
Davy8

null is string(string)null is stringC#でのnull参照の動作に慣れていない場合は、かなり直感的で、一時停止が必要になる場合があります。
decPL

24

nullリテラルは、に割り当てることができる任意の参照型。それ自体のタイプではありません。これは、null参照を表す特別なリテラルです。

場合にはis戻ってくるtrueときnullに渡される、あなたが行うことができる何でしょうnullリテラル?何も-それはありませんnulltrue混乱する問題を除いて、それが戻る点は何でしょうか?


とにかく-それがどれほど直感的であるかという点で、英語でコードを読んで教えてください:

null is string;

それを見ると、質問をしているようis "nothing" a string?です。私の直感は、いいえ、そうではないことを教えてくれます-それはそうnothingです。


大丈夫ですが、それも文字列ですよね?しかし、なぜその時は(null is string)フレイズを返すのでしょうか?
Gebb

私はそれを逆に言ったでしょう。参照型はすべてnullにすることができます。nullはnullです。
Mark H

@Odedなので、null値はオブジェクトタイプなどの有効な値ですか?このタイプの変数に割り当てることができますよね?だから答えはイエスのようです、値は完全に有効です、そして私の推測では(null is object)式はそれを正確にチェックするべきだと思います。
Gebb

@Gebb:ValueTypeはオブジェクトでもあり、参照型ではないことを忘れないでください。
Mark H

1
@Oded:「混乱する問題を除いて、それがtrueに戻る点は何ですか?」実際、それは言語をより論理的にするでしょう。次の2つの点を考慮してください。(1)is演算子は、参照(ここでは他のタイプの変換は不要)変換が存在するかどうかを確認します。(2)nullは、任意の参照型に変換できます。したがって(null is T)、Tが参照型の場合、trueを返す必要があります。しかし、いいえ、ここには明確な例外があります。これは私を混乱させるものです。
Gebb

12

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

is式は、次の条件の両方が満たされた場合にtrueと評価されます。

  • 式がnullではありません。
  • 式は型にキャストできます。つまり、型(式)のキャスト式は、例外をスローせずに完了します詳細については、7.6.6キャスト式を参照してください。

1
とにかく、ドキュメントには式はnullにできないこと(既にわかっている)とだけ記載されていますが、理由はわかりません
ユーザー名

なぜ他の方法でそれをしたいのですか?
悲惨な変数

1
@username:この回答は、それが機械的に機能する方法を説明し、使用するモデルを提供する参照を引用します。ここで宇宙の意味を尋ねています。私たちの神がSOに頻繁に
出かけるの

10

実際問題として、「null is T == false」とすると、余分なコードを入力する手間が省けます。

言う代わりに

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

私はただ言うことができます

if (X is Foo) {}

そしてそれで終わります。


8

null

それは問題の核心に到達するように思われるので、私はあなたの質問からこれを引用しました。null 値ではありません -値がないことです。is私にとっての目的は、質問に答えることです:

にキャストEした場合T、正常に取得されTますか?

これで、エラーなしでキャストできますが、キャストnullした後、「を持っている」ことはありません -それでも何も得られません。したがって、「is」はそうではないため、falseを返します。T TnullTis


3

Javaには、まったく同じことを行う演算子がありますが、はるかに長い名前がありますinstanceofnull instanceof Stringnullは何のインスタンスでもないため、false を返すことは非常に直感的Stringです。したがって、使用するときnull Javaのバージョンすると、より直感的になります。

ただし、これらの演算子はどちらも、階層全体を調べるように要求された場合にtrueを返します。例えば。インスタンスがあればStringですObject。そして、ここでは、とC#(インスタンスは実際には1つ、非常に特定のタイプを持っているので) 'Sさんは、あまり直感的なビットというJavaのだis、すべてがあるため(より直感的ですString Object奥)。

結論:かなり高度なロジックを1つの単語で表現しようとすると、混乱する人が少なくなります。ほとんどの人が1つの意味で同意し、同意しない人は調整しなければならなかったようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.