Por que o operador is retorna false quando nulo?


135

Parece-me que o isoperador é um pouco inconsistente.

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

Espera-se que o nullvalor pertença a qualquer tipo de referência (ou anulável). E, de fato, a especificação da linguagem C # diz algo que suporta essa hipótese, por exemplo (6.1.6 Conversões implícitas de referência):

As conversões implícitas de referência são:
...
• Do literal nulo a qualquer tipo de referência.

A descrição (7.10.10 O operador is) do isoperador começa dizendo que a expressão (E is T)resultará verdadeira quando existir uma conversão de referência Epara T, mas os autores continuarão excluindo explicitamente o caso quando Eé o nullliteral ou tem um nullvalor .

porque eles fazem aquilo? Para mim, parece contra-intuitivo.


Nula por que eles explicitamente excluídos é na melhor das hipóteses uma pergunta para programmers.stackoverflow.com
Variable Miserable

2
Eu não posso rescindir o meu voto perto, mas estas questões são muito bem aqui: meta.stackexchange.com/questions/36850/...
Merlyn Morgan-Graham

em java null typeof Objecttambém retorna false
catraca aberração

Suponha que null is stringeram true, e isso implicava que nullé um string. Suponha também que null is Nullable<int>seja true, o que implica que nullé a Nullable<int>. Agora, responda a esta pergunta: de que tipo é null?
um CVn

1
@ Michael Kjörling: Não sequitur. A partir dos fatos mencionados (null é uma string, null é um Nullable <int>), não se segue que eu seja capaz de responder a essa pergunta.
Gebb

Respostas:


195

Esta questão foi o assunto do meu blog em 30 de maio de 2013 . Obrigado pela ótima pergunta!


Você está olhando para uma entrada de automóveis vazia.

Alguém pergunta a você "sua entrada de automóveis pode segurar um Honda Civic?"

Sim. Sim pode.

Alguém aponta você para uma segunda entrada. Também está vazio. Eles perguntam "O conteúdo atual da minha entrada pode se encaixar na sua entrada?"

Sim, obviamente. Ambas as entradas estão vazias! Então, claramente, o conteúdo de um pode caber no outro, porque também não há conteúdo.

Alguém lhe pergunta "A sua entrada de automóveis contém um Honda Civic?"

Não, não tem.

Você está pensando que o isoperador responde à segunda pergunta: dado esse valor, ele se encaixa em uma variável desse tipo? Uma referência nula se encaixa em uma variável desse tipo? Sim.

Essa não é a pergunta que o isoperador responde. A pergunta que o isoperador responde é a terceira pergunta. y is Xnão pergunta " é yum valor legal de uma variável do tipo X? ", pergunta " É yuma referência válida para um objeto do tipo X? " Como uma referência nula não é uma referência válida para qualquer objeto de qualquer tipo, a resposta é "não " Aquela entrada está vazia; não contém um Honda Civic.

Outra maneira de ver isso é que y is Xresponde à pergunta "se eu dissesse y as X, obteria um resultado não nulo? Se y for nulo, claramente a resposta é não!


Para analisar um pouco mais a fundo sua pergunta:

Espera-se que o valor nulo pertença a qualquer tipo de referência (ou anulável)

Alguém poderia assumir implicitamente que um tipo é um conjunto de valores e que a compatibilidade da atribuição de um valor y com uma variável do tipo X não é nada mais nem menos do que verificar se y é um membro do conjunto x .

Embora essa seja uma maneira extremamente comum de ver tipos, essa não é a única maneira de ver tipos, e não é a maneira como o C # olha para tipos. Referências nulas são membros de nenhum tipo em C #; compatibilidade de atribuição não é apenas verificar um conjunto para ver se ele contém um valor. Só porque uma referência nula é uma atribuição compatível com uma variável do tipo de referência X não significa que nulo é um membro do tipo X. A atribuição "é compatível com" relação e a relação "é um membro do tipo" obviamente possui muitas se sobrepõem, mas não são idênticos no CLR.

Se as reflexões sobre a teoria dos tipos lhe interessam, confira meus artigos recentes sobre o assunto:

O que é isso que você chama de "tipo"? Parte um

O que é isso que você chama de "tipo"? Parte dois


@ Gebb: Fico feliz em ajudar. Este artigo também pode ser do seu interesse: blogs.msdn.com/b/ericlippert/archive/2010/09/16/…
Eric Lippert

Eric transformou isso em um post no blog: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Kevin Cathcart

y is Xnão pergunta "é yum valor legal de uma variável do tipo X?" Ele pergunta "É yuma referência válida para um objeto do tipo X?" Aquele foi o ponto principal! obrigado!
Jalal

Mas se eu perguntar y is int?, então eu perguntaria "Sua entrada contém um Honda Civic ou nada?". Por que a resposta ainda é negativa quando a garagem está vazia? Se você olhar por baixo do capô, a situação só piora, pois a pergunta se torna "Sua entrada de automóveis contém um Honda Civic ou uma placa que diz 'Não há Honda Civic aqui'?". Mesmo que sua entrada de automóveis contenha o referido sinal, a resposta ainda é não.
Fax

1
@ Gerard: Quando eu dou respostas longas e verbais, as pessoas me dizem que devem ser mais curtas e, quando eu dou respostas concisas e lacônicas, as pessoas me dizem que devem ser mais longas. Minha conclusão é: as pessoas gostam de reclamar. Como você tem sentimentos sobre o que é uma boa resposta para essa pergunta de oito anos de idade, minha sugestão é que você nos mostre o que é uma boa resposta respondendo por si mesmo, para que possamos aprender.
Eric Lippert

24

Eu acho que null is stringretornar falso é muito intuitivo. Nulo não significa nada, e definitivamente não é uma string. Portanto, ele deve retornar falso. Embora seja uma escolha que os designers de linguagem fizeram, é muito intuitiva quando você considera o significado do mundo real como nulo.


2
+1 porque a pergunta é realmente intuitiva e não está questionando as especificações, das quais o OP já está ciente. Se você perguntar a ele como uma frase Inglês "é nulluma string" a resposta é não, não é, o que é diferente de "é nullatribuído a string"
Davy8

null is stringé bastante intuitivo, (string)null is stringpode exigir uma pausa se você não estiver realmente familiarizado com o funcionamento de uma referência nula em C #.
decPL 5/05

24

O nullliteral pode ser atribuído a qualquer tipo de referência. É não um tipo em um de si mesmo. É um literal especial que representa uma referência nula.

No caso em que isretornaria truequando um nullpassasse, o que você seria capaz de fazer com o nullliteral? Nada - é null. Qual seria o sentido de retornar, trueexceto por questões confusas?


Independentemente disso - em termos de quão intuitivo isso é, leia o código em inglês e me diga:

null is string;

Quando vejo isso, parece estar fazendo a pergunta is "nothing" a string?. Minha intuição me diz que não, não é - é nothing.


Tudo bem, mas também é uma string, certo? Mas por que (null is string)retornar a base então?
Gebb 3/10/11

Eu teria formulado o contrário. Qualquer tipo de referência pode ser nulo. null é apenas nulo.
Mark H

@Oded, então o valor nulo é um valor válido, digamos, do tipo de objeto? Eu posso atribuí-lo a uma variável desse tipo, certo? Portanto, a resposta parece ser sim, o valor é perfeitamente válido, e meu palpite é que a (null is object)expressão deve verificar exatamente isso.
Gebb 3/10/11

@ Gebb: Não se esqueça que ValueTypes também são objetos, mas não tipos de referência.
Mark H

1
@Oded: "Qual seria o sentido de retornar verdadeiro, exceto por questões confusas?" Na verdade, isso tornaria a linguagem mais lógica. Considere estes dois pontos: (1) o isoperador verifica se existe uma conversão de referência (não precisamos de outros tipos de conversão aqui); (2) nullpode ser convertido para qualquer tipo de referência. Portanto (null is T), onde T é um tipo de referência deve retornar true. Mas não, aqui temos essa exceção explícita, que é o que me parece confuso.
Gebb

12

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

Uma expressão is é avaliada como true se as duas condições a seguir forem atendidas:

  • expressão não é nula.
  • expressão pode ser convertida para digitar. Ou seja, uma expressão de conversão do formulário (tipo (expressão) será concluída sem gerar uma exceção.Para obter mais informações, consulte 7.6.6 Expressões de conversão.

1
De qualquer forma a documentação indica apenas que a expressão não pode ser nulo (que já sabemos), mas não dizer por que
nome de usuário

Por que você iria querer de outra maneira?
Variável miserável

1
@username: Esta resposta explica como funciona mecanicamente e cita uma referência, que fornece um modelo para você trabalhar. Você está perguntando o significado do universo aqui. Eu acho que você tem sorte que nosso deus freqüenta SO;)
Merlyn Morgan-Graham

10

Por uma questão prática, ter "nulo é T == falso" me salva digitando um código extra:

Em vez de ter que dizer

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

Eu posso apenas dizer

if (X is Foo) {}

e acabar com isso.


8

o nullvalor

Citei isso da sua pergunta porque parece chegar ao cerne da questão. null não é um valor - é a ausência de um valor. O objetivo de ismim parece ser responder à pergunta:

Se eu expulso Epara T, vou receber com sucesso um T?

Agora, enquanto você pode converter nullpara T sem erro , depois de fazer isso, você não "tem um T" - ainda não tem nada. Portanto, não é o caso null"is" a T, então isretorna false.


3

Em Java existe um operador que faz exatamente o mesmo, mas tem muito mais nome: instanceof. É muito intuitivo lá que null instanceof Stringretorna false, porque null não é uma instância de nada, muito menos a String. Então, ao usarnull a versão do Java, é um pouco mais intuitivo.

No entanto, esses dois operadores retornam true quando solicitados a examinar toda a hierarquia também. Por exemplo. se instância de Stringé um Object. E aqui está o Java que é um pouco menos intuitivo (porque uma instância realmente tem um tipo muito específico) e os C # issão mais intuitivos (porque cada um String é umObject dentro de profundidade).

Conclusão: se você tentar descrever uma lógica bastante avançada em uma palavra, terá poucas pessoas confusas, de uma maneira ou de outra. Parece que a maioria das pessoas concordou com um significado e aqueles que não concordaram tiveram que se ajustar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.