Quando uma girafa não é uma girafa?

23

Espero que esse tipo de "enigma" seja onópico em Programação de quebra-cabeças e código de golfe.

Dê um exemplo de uma situação em que o método C # abaixo retornafalse :

public class Giraffe : Animal
{
  public bool Test()
  {
    return this is Giraffe;
  }
}

Regras: As linhas de código acima não devem ser alteradas de forma alguma, mas você colocaria o código em um aplicativo para que o "projeto" seja compilado e o método seja chamado. Quando executado, o método deve retornar false. A solução que tenho em mente, não emite sua própria IL em tempo de execução ou coisas "exóticas" semelhantes, é uma chamada de método de instância comum.

Jeppe Stig Nielsen
fonte
2
Com "o método é chamado", você quer dizer que isso Giraffe giraffe = new Giraffe(); giraffe.Test(); deve ocorrer de alguma forma, para que a linha desse método seja, de fato, executada?
Jesse C. Slicer
@ JesseC.Slicer Sim, na solução que tenho em mente, essa linha ocorre. É claro que poderia ser interessante ver outras soluções nas quais eu não pensava também. Então, se você tem algo, publique-o!
Jeppe Stig Nielsen
1
Bem, minha solução simples se parece mais Animal giraffe = new Giraffe(); giraffe.Test();e a classe pai Animaltem um Test()método que retorna false. Isso está enganando um pouco, pois chama o método de classe pai, e não o método Giraffe. Mas o site de chamada parece o mesmo.
Jesse C. Slicer
@ JesseC.Slicer Ah, entendo. Eu diria que, com a sua "solução", não é o "método abaixo" (como diz o meu problema) que retorna false, então não diria que era uma solução completa. Mas ainda interessante. Minha solução não tem nenhum método oculto (dica), mas como eu disse, outras soluções também podem ser interessantes.
Jeppe Stig Nielsen

Respostas:

28

Yay, encontrei!

public class Animal
{
    public class Giraffe { } // 1
}
public class Giraffe : Animal // 2
{
    public bool Test()
    {
        return this is Giraffe;
    }
}

Como Giraffe 1é membro Animale Giraffe 2está um nível mais adiante, o nome Giraffeno isteste refere-se ao primeiro (seção 7.6.2 na especificação C # 5).

Visual Studio mostra um aviso para this is Giraffe:

A expressão fornecida nunca é do tipo fornecido

o que é obviamente verdade, já que é o ponto principal :)

Você não pode colocar Giraffe 1diretamente dentro Giraffe 2, porque

nomes de membros não podem ser iguais ao seu tipo de anexo

- mas essa regra não existe para classes derivadas.

Belo problema, demorei um pouco.

balpha
fonte
11
Bem jogado senhor
Marc Gravell
2
Sim, esta foi a solução que eu tinha em mente! Portanto, existem dois tipos, um aninhado TheNamespace.Animal.Giraffeque também pode ser chamado por causa da herança TheNamespace.Giraffe.Giraffee um não aninhado TheNamespace.Giraffe. Sua referência à especificação C # é relevante! Você pode se livrar do aviso do compilador. Apenas altere o tipo aninhado da classe base de classpara interface. Nesse caso, alguém pode derivar ainda mais do não aninhado Giraffe e implementar o aninhado Giraffetambém; nesse caso, o compilador não pode reclamar; é uma verificação do tipo "justo".
Jeppe Stig Nielsen
1
Não entendo essa solução - pode ser porque não conheço muito c #. Eu não gosto disso jogando em nomes. Acho a solução do @ JesseC.Slicer muito mais inteligente.
Nicolas Barbulesco 30/05