¿Cuándo una jirafa no es una jirafa?

23

Espero que este tipo de "acertijo" sea un tema de programación en Puzzles y Code Golf.

Dé un ejemplo de una situación en la que el siguiente método de C # devuelvefalse :

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

Reglas: Las líneas de código anteriores no deben cambiarse de ninguna manera, pero debe colocar el código en una aplicación para que se compile el "proyecto" y se llame al método. Cuando se ejecuta, el método debe regresar false. La solución que tengo en mente, no emite su propia IL en tiempo de ejecución o cosas "exóticas" similares, es una llamada de método de instancia ordinaria.

Jeppe Stig Nielsen
fuente
2
Por "el método se llama", ¿quiere decir que Giraffe giraffe = new Giraffe(); giraffe.Test(); debe ocurrir de alguna manera para que la línea de ese método se ejecute?
Jesse C. Slicer
@ JesseC.Slicer Sí, en la solución que tengo en mente, esa línea ocurre. Por supuesto, podría ser interesante ver otras soluciones en las que no he pensado también. Entonces, si tienes algo, ¡publícalo!
Jeppe Stig Nielsen
1
Bueno, mi solución simple se parece más Animal giraffe = new Giraffe(); giraffe.Test();y la clase padre Animaltiene un Test()método que devuelve false. Eso es un poco engañoso, ya que llama al método de la clase padre en lugar del Giraffe's. Pero el sitio de la llamada se ve igual.
Jesse C. Slicer
@ JesseC.Slicer Ah, ya veo. Yo diría que con su "solución" no es el "método a continuación" (como dice en mi problema) lo que regresa false, por lo que no diría que fue una solución completa. Pero interesante aún. Mi solución no tiene ningún método de ocultación (pista), pero como dije, otras soluciones también podrían ser interesantes.
Jeppe Stig Nielsen

Respuestas:

28

Yay, lo encontré!

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

Como Giraffe 1es miembro Animaly Giraffe 2está un nivel más allá, el nombre Giraffeen la isprueba se refiere al primero (sección 7.6.2 en la especificación C # 5).

Visual Studio muestra una advertencia para this is Giraffe:

La expresión dada nunca es del tipo proporcionado

lo cual es obviamente cierto, ya que es todo el punto :)

No se puede poner Giraffe 1directamente adentro Giraffe 2, porque

los nombres de los miembros no pueden ser iguales a su tipo adjunto

- pero dicha regla no existe para las clases derivadas.

Buen problema, me llevó un tiempo.

balpha
fuente
11
Bien jugado señor
Marc Gravell
2
Sí, ¡esta era la solución que tenía en mente! Por lo tanto, hay dos tipos, uno anidado TheNamespace.Animal.Giraffeque, por herencia, también se puede llamar TheNamespace.Giraffe.Giraffey otro no anidado TheNamespace.Giraffe. ¡Su referencia a la especificación de C # es relevante! Puede deshacerse de la advertencia del compilador. Simplemente cambie el tipo anidado de la clase base de classa interface. En ese caso, alguien podría derivar más de lo no anidado Giraffe e implementarlo Giraffetambién, por lo que en ese caso el compilador no puede quejarse; es un cheque de tipo "justo".
Jeppe Stig Nielsen
1
No entiendo esta solución, eso puede deberse a que no sé mucho de C #. No me gusta jugar con nombres. La solución de @ JesseC.Slicer me parece mucho más inteligente.
Nicolas Barbulesco