La siguiente es una pregunta de entrevista. Se me ocurrió una solución, pero no estoy seguro de por qué funciona.
Pregunta:
Sin modificar la Sparta
clase, escriba un código que MakeItReturnFalse
devuelva false
.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
Mi solución: (SPOILER)
public class Place
{
public interface Sparta { }
}
Pero ¿por qué no Sparta
en MakeItReturnFalse()
referencia a {namespace}.Place.Sparta
su lugar de {namespace}.Sparta
?
c#
inheritance
types
namespaces
budi
fuente
fuente
Respuestas:
Básicamente, porque eso es lo que dicen las reglas de búsqueda de nombres. En la especificación C # 5, las reglas de nomenclatura relevantes están en la sección 3.8 ("Espacio de nombres y nombres de tipo").
Los primeros dos puntos, truncados y anotados, se leen:
Entonces, ese último punto es lo que recoge la
Sparta
clase si el primer punto no encuentra nada ... pero cuando la clase basePlace
define una interfazSparta
, se encuentra antes de considerar laSparta
clase.Tenga en cuenta que si hace que el tipo anidado sea
Place.Sparta
una clase en lugar de una interfaz, aún se compila y regresafalse
, pero el compilador emite una advertencia porque sabe que una instancia deSparta
nunca será una instancia de la clasePlace.Sparta
. Del mismo modo, si mantienePlace.Sparta
una interfaz pero hace laSparta
clasesealed
, recibirá una advertencia porque ningunaSparta
instancia podría implementar la interfaz.fuente
Sparta
clase original ,this is Place
retornostrue
. Sin embargo, agregarpublic interface Place { }
a laSparta
clase hacethis is Place
que regresefalse
. Hace girar mi cabeza.Place
como la interfaz.Al resolver un nombre a su valor, la "cercanía" de la definición se utiliza para resolver ambigüedades. Cualquier definición que sea "más cercana" es la que se elige.
La interfaz
Sparta
se define dentro de una clase base. La claseSparta
se define en el espacio de nombres que contiene. Las cosas definidas dentro de una clase base están "más cerca" que las cosas definidas en el mismo espacio de nombres.fuente
Hermosa pregunta! Me gustaría agregar una explicación un poco más larga para aquellos que no hacen C # a diario ... porque la pregunta es un buen recordatorio de los problemas de resolución de nombres en general.
Tome el código original, ligeramente modificado de las siguientes maneras:
return this is Sparta
).Athena
en laPlace
superclase para ilustrar la resolución del nombre de la interfaz.this
ya que está vinculado en laSparta
clase, solo para aclararlo todo.El código se ve así:
Ahora creamos un
Sparta
objeto y llamamos a los tres métodos.El resultado que obtenemos es:
Sin embargo, si modificamos la clase Place y definimos la interfaz Sparta:
entonces es esto
Sparta
, la interfaz, lo que estará disponible primero para el mecanismo de búsqueda de nombres y la salida de nuestro código cambiará a:Por lo tanto, nos hemos equivocado con la comparación de tipos en la
MakeItReturnFalse
definición de la función simplemente definiendo la interfaz Sparta en la superclase, que se encuentra primero por la resolución de nombre.Pero, ¿por qué C # eligió priorizar las interfaces definidas en la superclase en la resolución de nombres? @JonSkeet lo sabe! Y si lee su respuesta, obtendrá los detalles del protocolo de resolución de nombres en C #.
fuente