Kiedy żyrafa nie jest żyrafą?

23

Mam nadzieję, że ten rodzaj „zagadki” jest ontopyczny w Programowaniu łamigłówek i Code Golf.

Podaj przykład sytuacji, w której poniższa metoda C # zwracafalse :

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

Reguły: Powyższe wiersze kodu nie mogą być w żaden sposób zmieniane, ale należy umieścić kod w aplikacji, aby kompilacja „projektu” i wywołanie metody Po uruchomieniu metoda musi zwrócić false. Rozwiązanie, które mam na myśli, nie emituje własnej IL w czasie wykonywania ani podobnych „egzotycznych” rzeczy, jest to zwykłe wywołanie metody instancji.

Jeppe Stig Nielsen
źródło
2
Czy przez „metodę nazywa się”, masz na myśli, że Giraffe giraffe = new Giraffe(); giraffe.Test(); musi się to zdarzyć, aby wiersz w tej metodzie został faktycznie wykonany?
Jesse C. Slicer
@ JesseC.Slicer Tak, w rozwiązaniu, które mam na myśli, ta linia występuje. Oczywiście może być interesujące zobaczenie innych rozwiązań, o których również nie pomyślałem. Więc jeśli masz coś, opublikuj to!
Jeppe Stig Nielsen
1
Cóż, moje proste rozwiązanie wygląda bardziej, Animal giraffe = new Giraffe(); giraffe.Test();a klasa nadrzędna Animalma Test()metodę, która zwraca false. To trochę oszukuje, ponieważ wywołuje metodę klasy nadrzędnej, a nie metodę Giraffe. Ale strona połączeń wygląda tak samo.
Jesse C. Slicer
@ JesseC.Slicer Ach, rozumiem. Twierdziłbym, że z twoim „rozwiązaniem” nie zwraca się „metoda poniżej” (jak mówi mój problem) false, więc nie powiedziałbym, że było to pełne rozwiązanie. Ale wciąż interesujące. Moje rozwiązanie nie ma żadnej metody ukrywania (podpowiedzi), ale jak powiedziałem, inne rozwiązania mogą być również interesujące.
Jeppe Stig Nielsen

Odpowiedzi:

28

Tak, znalazłem to!

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

Ponieważ Giraffe 1jest członkiem Animali Giraffe 2jest o jeden poziom dalej, nazwa Giraffew isteście odnosi się do pierwszej (sekcja 7.6.2 specyfikacji C # 5).

Visual Studio wyświetla ostrzeżenie dla this is Giraffe:

Podane wyrażenie nigdy nie jest podanego typu

co jest oczywiście prawdą, ponieważ o to chodzi :)

Nie możesz umieścić Giraffe 1bezpośrednio w środku Giraffe 2, ponieważ

nazwy członków nie mogą być takie same jak ich typ zamknięcia

- ale taka zasada nie istnieje dla klas pochodnych.

Niezły problem, zajęło mi to trochę czasu.

balpha
źródło
11
Dobrze zagrany sir
Marc Gravell
2
Tak, to było rozwiązanie, które miałem na myśli! Istnieją więc dwa typy, jeden zagnieżdżony, TheNamespace.Animal.Giraffektóry z powodu dziedziczenia można również wywołać TheNamespace.Giraffe.Giraffe, a drugi nie zagnieżdżony TheNamespace.Giraffe. Twoje odniesienie do specyfikacji C # jest istotne! Możesz pozbyć się ostrzeżenia kompilatora. Wystarczy zmienić zagnieżdżony typ klasy podstawowej z classna interface. W takim przypadku ktoś może czerpać dalej z nie zagnieżdżonego Giraffe i zaimplementować również zagnieżdżony Giraffe, więc w takim przypadku kompilator nie może narzekać; jest to „sprawiedliwy” typ kontroli.
Jeppe Stig Nielsen
1
Nie rozumiem tego rozwiązania - być może dlatego, że nie znam dużo C #. Nie lubię tego, gdy gram na imionach. Rozwiązanie @ JesseC.Slicer uważam za znacznie sprytniejsze.
Nicolas Barbulesco