O seguinte é uma pergunta da entrevista. Eu vim com uma solução, mas não sei por que isso funciona.
Questão:
Sem modificar a Sparta
classe, escreva algum código que MakeItReturnFalse
retorne false
.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
Minha solução: (SPOILER)
public class Place
{
public interface Sparta { }
}
Mas por que Sparta
em MakeItReturnFalse()
referem-se {namespace}.Place.Sparta
, em vez de {namespace}.Sparta
?
c#
inheritance
types
namespaces
budi
fonte
fonte
Respostas:
Basicamente, porque é o que dizem as regras de pesquisa de nome. Na especificação C # 5, as regras de nomenclatura relevantes estão na seção 3.8 ("Namespace e nomes de tipo").
O primeiro par de marcadores - truncados e anotados - dizia:
Portanto, esse ponto final é o que seleciona a
Sparta
classe se o primeiro marcador não encontrar nada ... mas quando a classe basePlace
define uma interfaceSparta
, ela é encontrada antes de considerarmos aSparta
classe.Observe que, se você tornar o tipo aninhado
Place.Sparta
uma classe em vez de uma interface, ele ainda compila e retornafalse
- mas o compilador emite um aviso porque sabe que uma instância deSparta
nunca será uma instância da classePlace.Sparta
. Da mesma forma, se você mantiverPlace.Sparta
uma interface, mas fizer aSparta
classesealed
, receberá um aviso porque nenhumaSparta
instância jamais poderia implementar a interface.fonte
Sparta
classe original ,this is Place
retornatrue
. No entanto, adicionarpublic interface Place { }
àSparta
classe fazthis is Place
com que retornefalse
. Faz minha cabeça girar.Place
como interface.Ao resolver um nome com seu valor, a "proximidade" da definição é usada para resolver ambiguidades. Qualquer definição que seja "mais próxima" é a que é escolhida.
A interface
Sparta
é definida dentro de uma classe base. A classeSparta
é definida no espaço para nome que contém. As coisas definidas em uma classe base são "mais próximas" do que as definidas no mesmo espaço para nome.fonte
Bela pergunta! Gostaria de adicionar uma explicação um pouco mais longa para quem não faz C # diariamente ... porque a pergunta é um bom lembrete dos problemas de resolução de nomes em geral.
Pegue o código original, ligeiramente modificado das seguintes maneiras:
return this is Sparta
).Athena
naPlace
superclasse para ilustrar a resolução do nome da interface.this
como está vinculado naSparta
classe, apenas para deixar tudo muito claro.O código fica assim:
Agora criamos um
Sparta
objeto e chamamos os três métodos.A saída que obtemos é:
No entanto, se modificarmos a classe Place e definirmos a interface Sparta:
então é isso
Sparta
- a interface - que estará disponível primeiro para o mecanismo de pesquisa de nome e a saída do nosso código será alterada para:Então, nós estragamos efetivamente a comparação de tipos no
MakeItReturnFalse
definição de função, apenas definindo a interface Sparta na superclasse, que é encontrada primeiro pela resolução de nomes.Mas por que o C # optou por priorizar as interfaces definidas na superclasse na resolução de nomes? @JonSkeet sabe! E se você ler a resposta dele, obterá os detalhes do protocolo de resolução de nomes em C #.
fonte