Perché l'operatore is restituisce false quando viene dato null?


135

Mi sembra che l' isoperatore sia un po 'incoerente.

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

Ci si aspetta che il nullvalore appartenga a qualsiasi tipo di riferimento (o nullable). E in effetti, la specifica del linguaggio C # dice qualcosa che supporta questa ipotesi, ad esempio (6.1.6 Conversioni di riferimento implicite):

Le conversioni di riferimento implicite sono:
...
• Dal valore letterale null a qualsiasi tipo di riferimento.

La descrizione (7.10.10 L'operatore è) isdell'operatore inizia dicendo che l'espressione (E is T)risulterà vera quando esiste una conversione di riferimento da Ein T, ma poi gli autori proseguono escludendo esplicitamente il caso in cui Eè nullletterale o ha un nullvalore .

Perché lo fanno? A me sembra controintuitivo.


Perché hanno esplicitamente escluso null è nella migliore delle ipotesi una domanda per programmers.stackoverflow.com
Miserable Variable

2
Non posso annullare il mio voto ravvicinato, ma queste domande vanno bene qui: meta.stackexchange.com/questions/36850/…
Merlyn Morgan-Graham,

in java null typeof Objectrestituisce anche false
ratchet maniaco

Supponiamo che lo null is stringfossero truee questo implicava che nulla string. Supponi anche che null is Nullable<int>sia true, sottintendendo che nullè a Nullable<int>. Ora, rispondi a questa domanda: di che tipo è null?
un CVn

1
@Michael Kjörling: Non sequitur. Dai fatti citati (null è una stringa, null è una nullulla <int>) non ne consegue che dovrei essere in grado di rispondere a questa domanda.
Gebb,

Risposte:


195

Questa domanda è stata oggetto del mio blog il 30 maggio 2013 . Grazie per l'ottima domanda!


Stai fissando un vialetto vuoto.

Qualcuno ti chiede "il tuo vialetto può contenere una Honda Civic?"

Sì. Sì, può.

Qualcuno ti indica un secondo vialetto. È anche vuoto. Chiedono "Il contenuto attuale del mio vialetto può adattarsi al tuo vialetto?"

Sì, ovviamente. Entrambi i passi carrai sono vuoti! Quindi chiaramente il contenuto di uno può adattarsi all'altro, perché non ci sono contenuti di nessuno dei due in primo luogo.

Qualcuno ti chiede "Il tuo vialetto contiene una Honda Civic?"

No non lo fa.

Stai pensando che l' isoperatore risponda alla seconda domanda: dato questo valore, si adatta a una variabile di quel tipo? Un riferimento null rientra in una variabile di questo tipo? Sì lo fa.

Non è questa la domanda a cui l' isoperatore risponde. La domanda a cui l' isoperatore risponde è la terza domanda. y is Xnon chiede " è yun valore legale di una variabile di tipo X? " Chiede " È yun riferimento valido a un oggetto di tipo X? " Poiché un riferimento null non è un riferimento valido a nessun oggetto di qualsiasi tipo, la risposta è "no ". Quel vialetto è vuoto; non contiene una Honda Civic.

Un altro modo di guardare è che y is Xrisponde alla domanda "se dicessi y as X, otterrei un risultato non nullo? Se y è nullo, chiaramente la risposta è no!


Per approfondire la tua domanda:

Ci si aspetta che il valore null appartenga a qualsiasi tipo di riferimento (o nullable)

Si suppone implicitamente che un tipo sia un insieme di valori e che la compatibilità di assegnazione di un valore y con una variabile di tipo X non sia altro né meno che verificare se y sia un membro dell'insieme x .

Anche se questo è un modo estremamente comune di guardare i tipi, non è l' unico modo di guardare i tipi, e non è il modo in cui C # guarda i tipi. I riferimenti null sono membri di nessun tipo in C #; la compatibilità delle assegnazioni non sta semplicemente verificando un set per vedere se contiene un valore. Solo perché un riferimento null è compatibile con l'assegnazione con con una variabile di tipo X di riferimento non significa che null sia un membro di tipo X. La relazione "è un'assegnazione compatibile con" e la relazione "è un membro di tipo" ovviamente ha un sacco di si sovrappongono, ma non sono identici nel CLR.

Se ti interessano le riflessioni sulla teoria dei tipi, dai un'occhiata ai miei recenti articoli sull'argomento:

Come si chiama questo "tipo"? Prima parte

Come si chiama questo "tipo"? Seconda parte


@Gebb: felice di aiutarti. Questo articolo potrebbe anche interessarti: blogs.msdn.com/b/ericlippert/archive/2010/09/16/…
Eric Lippert

Eric l'ha trasformato in un post sul blog: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Kevin Cathcart,

y is Xnon chiede "è yun valore legale di una variabile di tipo X?" Si chiede "È yun riferimento valido a un oggetto di tipo X?" Questo era il punto! Grazie!
Jalal,

Ma se chiedessi y is int?, allora mi chiederei "Il tuo vialetto contiene una Honda Civic o niente?". Perché la risposta è ancora no quando il vialetto è vuoto? Se guardi sotto il cofano, la situazione peggiora, poiché la domanda diventa "La tua strada privata contiene una Honda Civic o un cartello che dice" No Honda Civic qui "?". Anche se il tuo vialetto contiene tale segno, la risposta è ancora no.
Fax

1
@Gerard: quando do risposte lunghe, verbose e loquaci, le persone mi dicono che dovrebbero essere più brevi, e quando do risposte concise e laconiche, le persone mi dicono che dovrebbero essere più lunghe. La mia conclusione è: alla gente piace lamentarsi. Dato che hai delle sensazioni su ciò che rende una buona risposta a questa domanda di otto anni, il mio suggerimento è di mostrarci ciò che rende una buona risposta rispondendola tu stesso, in modo che possiamo imparare.
Eric Lippert,

24

Penso che null is stringrestituire false sia molto intuitivo. Null non significa nulla, e sicuramente non è una stringa. Quindi dovrebbe restituire false. Sebbene sia una scelta fatta dai progettisti del linguaggio, è molto intuitivo se si considera il significato del mondo reale di null.


2
+1 perché la domanda riguarda davvero se è intuitiva e non mette in discussione le specifiche, di cui l'OP è già a conoscenza. Se la chiedi come una frase inglese "è nulluna stringa" la risposta è no, non lo è, che è diversa da "è nullassegnabile a string"
Davy8

null is stringè piuttosto intuitivo, (string)null is stringpotrebbe richiedere una pausa se non si ha familiarità con il funzionamento di un riferimento null in C #.
decPL

24

Il valore nullletterale può essere assegnato a qualsiasi tipo di riferimento. È non un tipo in sé. È un letterale speciale che rappresenta un riferimento null.

Nel caso che isritornasse truequando nullverrebbe passato un, cosa saresti in grado di fare con il nullletterale? Niente - lo è null. Quale sarebbe il suo ritorno truese non per questioni confuse?


Indipendentemente da ciò, in termini di quanto sia intuitivo, leggi il codice in inglese e dimmi:

null is string;

Quando lo vedo, sembra che stia ponendo la domanda is "nothing" a string?. La mia intuizione mi dice che no, non lo è - lo è nothing.


Va bene, ma poi è anche una stringa, giusto? Ma allora perché (null is string)restituire flase?
Gebb,

L'avrei espresso al contrario. Qualsiasi tipo di riferimento può essere nullo. null è solo null.
Segna H

@Oded quindi il valore null è un valore valido, diciamo, del tipo di oggetto? Posso assegnarlo a una variabile di questo tipo, giusto? Quindi la risposta sembra essere sì, il valore è perfettamente valido e la mia ipotesi è che l' (null is object)espressione dovrebbe verificare esattamente questo.
Gebb,

@Gebb: non dimenticare che ValueTypes sono anche oggetti, ma non tipi di riferimento.
Segna H

1
@Oded: "Quale sarebbe il punto in cui sarebbe tornato vero se non per questioni confuse?" In realtà, renderebbe il linguaggio più logico. Considera questi due punti: (1) l' isoperatore verifica se esiste una conversione di riferimento (non abbiamo bisogno di altri tipi di conversione qui); (2) nullpuò essere convertito in qualsiasi tipo di riferimento. Pertanto (null is T), dove T è un tipo di riferimento dovrebbe restituire true. Ma no, qui abbiamo quell'eccezione esplicita, che è ciò che mi sembra confuso.
Gebb,

12

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

Un'espressione is viene valutata su true se sono soddisfatte entrambe le seguenti condizioni:

  • l'espressione non è nulla.
  • espressione può essere lanciata per digitare. Ossia, un'espressione di cast del modulo (tipo (espressione) verrà completata senza generare un'eccezione. Per ulteriori informazioni, vedere 7.6.6 Espressioni di cast.

1
Comunque la documentazione afferma solo che l'espressione non può essere nulla (che già sappiamo), ma non dice perché
nome utente

Perché lo vorresti in un altro modo?
Miserabile variabile,

1
@nomeutente: questa risposta spiega il modo in cui funziona meccanicamente e cita un riferimento, che ti dà un modello con cui lavorare. Stai chiedendo il significato dell'universo qui. Immagino che tu sia fortunato che il nostro dio frequenta SO;)
Merlyn Morgan-Graham il

10

In pratica, avere "null is T == false" mi fa risparmiare digitando un codice extra:

Invece di dover dire

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

Posso solo dire

if (X is Foo) {}

ed essere fatto con esso.


8

il nullvalore

Ho citato questo dalla tua domanda perché sembra arrivare al nocciolo della questione. null non è un valore, è l'assenza di un valore. Lo scopo di isme sembra essere quello di rispondere alla domanda:

Se lancio Ea T, otterrò correttamente un T?

Ora, mentre si può lanciare nulla T senza errori , dopo aver fatto in modo da non "si dispone di un T" - niente hai ancora. Quindi non è il caso che null"sia" a T, quindi isrestituisce false.


3

In Java v'è un operatore che fa esattamente stessa cosa, ma ha nome molto più lungo: instanceof. È molto intuitivo lì che null instanceof Stringrestituisce false, perché null non è un'istanza di nulla, tanto meno a String. Quindi, quando si utilizzanull la versione di Java è un po 'più intuitivo.

Tuttavia, entrambi gli operatori restituiscono true quando viene richiesto di esaminare anche l'intera gerarchia. Per esempio. se istanza di Stringè un Object. E qui è Java che è un po 'meno intuitivo (perché un'istanza in realtà ne ha uno, un tipo molto specifico) e C # isè più intuitivo (perché ognuno String è un Objectprofondo dentro).

In conclusione: se si tenta di descrivere una logica piuttosto avanzata in una parola, si è tenuti a confondere poche persone, in questo modo o in un altro. Sembra che la maggior parte delle persone fosse d'accordo su un significato e quelli che non erano d'accordo, dovevano adattarsi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.