Quand une girafe n'est-elle pas une girafe?

23

J'espère que ce genre d'énigme est ontopique dans la programmation des puzzles et du code golf.

Donnez un exemple d'une situation où la méthode C # ci-dessous renvoiefalse :

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

Règles: Les lignes de code ci-dessus ne doivent en aucun cas être modifiées, mais vous mettriez le code dans une application pour que le «projet» se compile et que la méthode soit appelée. Lors de son exécution, la méthode doit revenir false. La solution que j'ai en tête, n'émet pas son propre IL au moment de l'exécution ou des choses "exotiques" similaires, c'est un appel de méthode d'instance ordinaire.

Jeppe Stig Nielsen
la source
2
Par "la méthode est appelée", voulez-vous dire que cela Giraffe giraffe = new Giraffe(); giraffe.Test(); doit se produire d'une manière ou d'une autre pour que la ligne de cette méthode soit, en fait, exécutée?
Jesse C. Slicer
@ JesseC.Slicer Oui, dans la solution que j'ai en tête, cette ligne se produit. Bien sûr, il pourrait être intéressant de voir d'autres solutions auxquelles je n'ai pas pensé aussi. Donc, si vous avez quelque chose, postez-le!
Jeppe Stig Nielsen
1
Eh bien, ma solution simple ressemble plus à Animal giraffe = new Giraffe(); giraffe.Test();et la classe parente Animala une Test()méthode qui retourne false. Cela triche un peu car il appelle la méthode de la classe parent plutôt que Giraffela sienne. Mais le site d'appel se ressemble.
Jesse C. Slicer
@ JesseC.Slicer Ah, je vois. Je dirais qu'avec votre "solution" ce n'est pas la "méthode ci-dessous" (comme il est dit dans mon problème) qui revient false, donc je ne dirais pas que c'était une solution complète. Mais intéressant quand même. Ma solution n'a pas de méthode de masquage (indice), mais comme je l'ai dit, d'autres solutions pourraient aussi être intéressantes.
Jeppe Stig Nielsen

Réponses:

28

Ouais, je l'ai trouvé!

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

Étant donné qu'il Giraffe 1est membre Animalet se Giraffe 2trouve un niveau plus loin, le nom Giraffedans le istest fait référence au premier (section 7.6.2 dans la spécification C # 5).

Visual Studio affiche un avertissement pour this is Giraffe:

L'expression donnée n'est jamais du type fourni

ce qui est évidemment vrai, puisque c'est tout l'intérêt :)

Vous ne pouvez pas mettre Giraffe 1directement à l'intérieur Giraffe 2, car

les noms des membres ne peuvent pas être les mêmes que leur type englobant

- mais une telle règle n'existe pas pour les classes dérivées.

Joli problème, ça m'a pris du temps.

balpha
la source
11
Bien joué monsieur
Marc Gravell
2
Oui, c'était la solution que j'avais en tête! Il existe donc deux types, l'un imbriqué TheNamespace.Animal.Giraffequi, en raison de l'héritage, peut également être appelé TheNamespace.Giraffe.Giraffe, et l'autre non imbriqué TheNamespace.Giraffe. Votre référence à la spécification C # est pertinente! Vous pouvez vous débarrasser de l'avertissement du compilateur. Changez simplement le type imbriqué de la classe de base de classen interface. Dans ce cas, quelqu'un pourrait dériver davantage du non-imbriqué Giraffe et l' implémenter Giraffeégalement, donc dans ce cas, le compilateur ne peut pas se plaindre; c'est une vérification de type «juste».
Jeppe Stig Nielsen
1
Je ne comprends pas cette solution - peut-être parce que je ne connais pas beaucoup C #. Je n'aime pas que ça joue sur les noms. Je trouve la solution de @ JesseC.Slicer beaucoup plus intelligente.
Nicolas Barbulesco