Warum gibt der is-Operator false zurück, wenn null angegeben wird?


135

Es scheint mir, dass der isOperator etwas inkonsistent ist.

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

Man erwartet, dass der nullWert zu einem beliebigen Referenztyp (oder nullwertfähigen Typ) gehört. Tatsächlich sagt die C # -Sprachenspezifikation etwas aus, das diese Hypothese unterstützt, zum Beispiel (6.1.6 Implizite Referenzkonvertierungen):

Die impliziten Referenzkonvertierungen sind:
...
• Vom Nullliteral zu einem beliebigen Referenztyp.

Die Beschreibung (7.10.10 Der Operator is) des isOperators beginnt mit der Aussage, dass der Ausdruck (E is T)wahr ist, wenn eine Referenzkonvertierung von Enach Tvorhanden ist. Anschließend schließen die Autoren den Fall explizit aus, wenn Edas nullLiteral ist oder einen nullWert hat .

Warum machen sie das? Mir scheint das nicht intuitiv zu sein.


Warum sie null explizit ausgeschlossen haben, ist bestenfalls eine Frage für programmers.stackoverflow.com
Miserable Variable

2
Ich kann meine enge Abstimmung nicht widerrufen
Merlyn Morgan-Graham

in Java gibt null typeof Objectauch falsch
Ratschenfreak

Nehmen wir an , null is stringwaren true, und dies impliziert , dass nulla string. Man nehme auch an , dass null is Nullable<int>ist true, was bedeutet , dass nullein ist Nullable<int>. Beantworten Sie nun diese Frage: Welcher Typ ist null?
ein CVn

1
@ Michael Kjörling: Nicht sequitur. Aus den genannten Fakten (null ist eine Zeichenfolge, null ist eine Nullable <int>) folgt nicht, dass ich diese Frage beantworten sollte.
Gebb

Antworten:


195

Diese Frage war das Thema meines Blogs am 30. Mai 2013 . Danke für die tolle Frage!


Sie starren auf eine leere Auffahrt.

Jemand fragt Sie: "Kann Ihre Auffahrt einen Honda Civic aufnehmen?"

Ja. Ja, kann es.

Jemand weist Sie auf eine zweite Auffahrt. Es ist auch leer. Sie fragen: "Kann der aktuelle Inhalt meiner Auffahrt in Ihre Auffahrt passen?"

Ja offensichtlich. Beide Einfahrten sind leer! So klar kann der Inhalt des einen in den anderen passen, weil es überhaupt keinen Inhalt von beidem gibt.

Jemand fragt Sie: "Enthält Ihre Auffahrt einen Honda Civic?"

Nein, tut es nicht.

Sie denken, dass der isOperator die zweite Frage beantwortet: Passt er angesichts dieses Werts in eine Variable dieses Typs? Passt eine Nullreferenz in eine Variable dieses Typs? Ja tut es.

Das ist nicht die Frage, die der isBediener beantwortet. Die Frage, die der isBediener beantwortet, ist die dritte Frage. y is Xfrage nicht „ ist yein Recht Wert einer Variable vom Typ X? “ Es fragt : „ Ist yeine gültige Referenz auf ein Objekt vom Typ X? “ Da eine Nullreferenz auf keine gültige Referenz jedes Objekt von jeder Art, ist die Antwort „nein ". Diese Auffahrt ist leer; Es enthält keinen Honda Civic.

Eine andere Sichtweise ist die y is XBeantwortung der Frage: "Wenn ich sagen y as Xwürde, würde ich ein Ergebnis ungleich Null erhalten? Wenn y null ist, lautet die Antwort eindeutig nein!"


Um Ihre Frage etwas genauer zu betrachten:

Man erwartet, dass der Nullwert zu einem beliebigen Referenztyp (oder Nullwerttyp) gehört

Man würde implizit annehmen, dass ein Typ eine Menge von Werten ist und dass die Zuweisungskompatibilität eines Wertes y mit einer Variablen vom Typ X nichts anderes als die Überprüfung ist, ob y ein Mitglied der Menge x ist .

Obwohl dies eine sehr verbreitete Art ist, Typen zu betrachten, ist dies nicht die einzige Art, Typen zu betrachten, und es ist nicht die Art, wie C # Typen betrachtet. Nullreferenzen sind Mitglieder ohne Typ in C #; Zuordnung Kompatibilität wird nicht überprüft lediglich einen Satz zu sehen , ob es einen Wert enthält. Nur weil ein NULL - Verweis ist Zuordnung kompatibel mit einem variablen Referenz Typ X bedeutet nicht , dass null ist Mitglied des Typ X. Des „ist Zuordnung kompatibel mit“ Beziehung und die „ist ein Mitglied des Typs“ Beziehung hat offensichtlich viel Überlappung, aber sie sind in der CLR nicht identisch.

Wenn Sie sich Gedanken über Typentheorie machen, lesen Sie meine neuesten Artikel zu diesem Thema:

Was ist das für ein Ding, das du "Typ" nennst? Teil eins

Was ist das für ein Ding, das du "Typ" nennst? Zweiter Teil


@Gebb: Freut mich zu helfen. Dieser Artikel könnte auch für Sie von Interesse sein: blogs.msdn.com/b/ericlippert/archive/2010/09/16/…
Eric Lippert

Eric verwandelte dies in einen Blog-Beitrag: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Kevin Cathcart

y is Xfragt nicht "ist yein legaler Wert einer Variablen vom Typ X?" Es fragt "Ist yein gültiger Verweis auf ein Objekt vom Typ X?" Das war der springende Punkt! Vielen Dank!
Jalal

Aber wenn ich frage y is int?, würde ich fragen: "Enthält Ihre Auffahrt einen Honda Civic oder nichts?". Warum lautet die Antwort immer noch nein, wenn Ihre Auffahrt leer ist? Wenn Sie unter die Motorhaube schauen, wird es nur noch schlimmer, wenn die Frage lautet: "Enthält Ihre Auffahrt einen Honda Civic oder ein Schild mit der Aufschrift" Kein Honda Civic hier "?". Selbst wenn Ihre Auffahrt dieses Schild enthält, lautet die Antwort immer noch nein.
Fax

1
@Gerard: Wenn ich lange, ausführliche, gesprächige Antworten gebe, sagen mir die Leute, dass sie kürzer sein sollten, und wenn ich prägnante, lakonische Antworten gebe, sagen mir die Leute, dass sie länger sein sollten. Mein Fazit lautet: Leute beschweren sich gerne. Da Sie Gefühle darüber haben, was eine gute Antwort auf diese acht Jahre alte Frage ausmacht, ist mein Vorschlag, dass Sie uns zeigen, was eine gute Antwort ausmacht, indem Sie sie selbst beantworten, damit wir lernen können.
Eric Lippert

24

Ich denke null is string, falsch zurückzugeben ist sehr intuitiv. Null bedeutet nichts und ist definitiv keine Zeichenfolge. Es sollte also false zurückgeben. Während es eine Wahl ist, die die Sprachdesigner getroffen haben, ist es eine sehr intuitive Wahl, wenn man die reale Bedeutung von Null betrachtet.


2
+1, weil es bei der Frage wirklich darum geht, ob es intuitiv ist und nicht um die Spezifikation, die dem OP bereits bekannt ist. Wenn Sie es als englischen Satz fragen "ist nulleine Zeichenfolge", ist die Antwort nein, es ist nicht, was sich von "ist nullzuweisbar auf string" unterscheidet
Davy8

null is stringist ziemlich intuitiv und (string)null is stringerfordert möglicherweise eine Pause, wenn Sie nicht wirklich mit der Funktionsweise einer Nullreferenz in C # vertraut sind.
Dezember

24

Das nullLiteral kann jedem Referenztyp zugeordnet werden. Es ist kein Typ an sich. Es ist ein spezielles Literal , das eine Nullreferenz darstellt.

Was könnten Sie mit dem Literal tun, wenn ein Fall eintreten iswürde, truewenn ein übergeben nullwürde null? Nichts - es ist null. Was wäre der Grund für eine Rückkehr, trueaußer für verwirrende Dinge?


Unabhängig davon - wie intuitiv das ist, lesen Sie den Code auf Englisch und sagen Sie mir:

null is string;

Wenn ich das sehe, scheint es die Frage zu stellen is "nothing" a string?. Meine Intuition sagt mir, dass nein, es ist nicht - es ist nothing.


Das ist in Ordnung, aber dann ist es auch eine Saite, oder? Aber warum (null is string)kehrt dann Flase zurück?
Gebb

Ich hätte es anders herum formuliert. Jeder Referenztyp kann null sein. null ist nur null.
Mark H

@Oded also ist der Nullwert ein gültiger Wert von beispielsweise dem Objekttyp? Ich kann es einer Variablen dieses Typs zuweisen, oder? Die Antwort scheint also ja zu sein, der Wert ist vollkommen gültig, und ich vermute, dass der (null is object)Ausdruck genau das überprüfen sollte.
Gebb

@Gebb: Vergessen Sie nicht, dass ValueTypes auch Objekte sind, aber keine Referenztypen.
Mark H

1
@Oded: "Was wäre der Sinn, wenn es wahr wäre, außer für verwirrende Dinge?" Eigentlich würde es die Sprache logischer machen. Betrachten Sie diese beiden Punkte: (1) Der isOperator prüft, ob eine Referenzkonvertierung (wir brauchen hier keine anderen Konvertierungsarten) vorhanden ist. (2) nullkann in einen beliebigen Referenztyp konvertiert werden. Wenn (null is T)T ein Referenztyp ist, sollte daher true zurückgegeben werden. Aber nein, hier haben wir diese explizite Ausnahme, die mir verwirrend erscheint.
Gebb

12

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

Ein is-Ausdruck wird als wahr ausgewertet, wenn beide der folgenden Bedingungen erfüllt sind:

  • Ausdruck ist nicht null.
  • Ausdruck kann in Typ umgewandelt werden. Das heißt, ein Besetzungsausdruck des Formulars (Typ (Ausdruck)) wird ohne Auslösen einer Ausnahme abgeschlossen. Weitere Informationen finden Sie unter 7.6.6 Besetzungsausdrücke.

1
Wie auch immer, die Dokumentation besagt nur, dass Ausdruck nicht null sein kann (das wissen wir bereits), aber es sagt nicht warum
Benutzername

Warum willst du es anders?
Elende Variable

1
@Benutzername: Diese Antwort erklärt die Funktionsweise mechanisch und zitiert eine Referenz, mit der Sie ein Modell zum Arbeiten erhalten. Sie fragen hier nach der Bedeutung des Universums. Ich denke du hast Glück, dass unser Gott SO besucht;)
Merlyn Morgan-Graham

10

In der Praxis erspart mir die Eingabe von "null ist T == false" die Eingabe von zusätzlichem Code:

Anstatt sagen zu müssen

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

Ich kann nur sagen

if (X is Foo) {}

und damit fertig sein.


8

der nullWert

Ich habe dies aus Ihrer Frage zitiert, weil es den Kern der Sache zu erreichen scheint. null ist kein Wert - es ist das Fehlen eines Wertes. Der Zweck von isscheint mir zu sein, die Frage zu beantworten:

Wenn ich geworfen Ezu T, werde ich eine erfolgreich bekommen T?

Jetzt, während Sie können gegossen , nullum T ohne Fehler , nachdem ich so dass Sie nicht „eine haben T“ - Sie haben noch bekam nichts. Es ist also nicht der Fall, dass null"ist" a T, also wird isfalse zurückgegeben.


3

In Java gibt es einen Operator, der genau dasselbe tut, aber einen viel längeren Namen hat : instanceof. Es ist dort sehr intuitiv, was null instanceof Stringfalse zurückgibt, da null keine Instanz von irgendetwas ist, geschweige denn a String. Wenn Sie also nulldie Java-Version verwenden, ist dies etwas intuitiver.

Beide Operatoren geben jedoch true zurück, wenn sie aufgefordert werden, auch die gesamte Hierarchie zu durchsuchen. Z.B. wenn Instanz von Stringist ein Object. Und hier ist es Java , dass das etwas weniger intuitiv (weil eine Instanz tatsächlich einen, sehr spezifische Art) und C # 's isintuitiver ist (denn jeder String ist ein Objecttief im Innern).

Fazit: Wenn Sie versuchen, eine ziemlich fortgeschrittene Logik in einem Wort zu beschreiben, werden auf die eine oder andere Weise nur wenige Menschen verwirrt sein. Es scheint, dass sich die meisten Menschen auf eine Bedeutung einigten und diejenigen, die nicht zustimmten, sich anpassen mussten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.