Pergunta

Output:
B-> Olá! a partir explícita.

que não deveria ser:?
A-> Olá! a partir explícita.

Por que o elenco não explícita (IHello) uma chamada IHello.Hello () da classe A?

interface IHello
{
    void Hello();
}

class A : IHello
{

    public virtual void Hello()
    {
        Console.WriteLine("A->Hello!");
    }

    void IHello.Hello()
    {
        Console.WriteLine("A->Hello! from Explicit.");
    }
}

class B : A, IHello
{
    public override void Hello()
    {
        Console.WriteLine("B->Hello!");
    }

    void IHello.Hello()
    {
        Console.WriteLine("B->Hello! from Explicit.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new B();
        ((IHello)a).Hello();
    }
}
Foi útil?

Solução

Não, não deveria.

A chamada para Hello é equivalente à comentou-out um - o caminho para a obtenção de um IHello não importa (a menos que requer verificação em tempo de execução ou conversão); o tipo de tempo de compilação é apenas IHello de qualquer forma, e o mapeamento interface é a mesma, contudo, você chegar lá.

Quando uma interface é explicitamente implementado mais de uma vez na hierarquia de tipo, a implementação no tipo mais derivado é usado. (Quando chamado através da interface.)

De secção 13.4.4 do C # 3.0 Especificação:

mapeamento de interface para uma classe ou struct C localiza uma implementação para cada membro de cada interface especificado na lista de classe base de C. A implementação de um determinado interface de i.m membro, onde I é a de interface na qual o elemento M é declarou, é determinada examinando cada classe ou struct S, começando com C e repetição para cada sucessivo classe de base de C, até que uma combinação é implantada:

  • Se S contém uma declaração de um membro de interface explícita implementação que corresponde I e M, em seguida, esse membro é a implementação de i.m..
  • Caso contrário, se S contém uma declaração de um membro do público não-estático que corresponde M, em seguida, esse membro é a implementação de IM Se mais de um partidas membros, é não especificado qual membro é a implementação de IM Esta situação só pode ocorrer se S é um tipo construído onde os dois membros declaradas no tipo genérico têm assinaturas diferentes, mas os argumentos de tipo fazer suas assinaturas idênticas.

Outras dicas

(A) um nada faz. A referência já está declarado como um modo lançando-a A não terá nenhum efeito.

Mesmo que sua referência é declarado como A, o objeto que ele se refere é do tipo B. Se você lançar esse objeto para IHello, uma chamada para Olá () irá chamar implementação explícita objeto do B de Olá.

A saída é exatamente como o esperado.

Não, quando você cria um new método (ToString), não é virtual. Novos meios apenas que você não me importo "esconder" a versão na classe base - por isso, se você chamá-lo com uma referência que você tenha convertido para um tipo específico (A), ele executa o método na classe A, independentemente do o tipo real do objeto que você está chamando. (Isto é, você chamou A.ToString () para que ele executou A.ToString ())

Quando você cria um virtual método, em seguida, independentemente do que você digite lançar a referência, a implementação do tipo real do objeto é utilizado (ou seja, você criou um B, então quando você chamada (qualquer que seja o objeto é) .Hello, que chamou B.Hello)

A diferença crucial é que uma chamada é virtual eo outro não é.

Não, não deveria.

Quando você está chamando um método virtual, não importa o que o tipo da referência é. O método que é chamado é determinada pelo tipo real do objecto, não do tipo de referência.

Como você cria uma instância do B classe, o tipo real do objeto é B. A razão que ele imprime "This is class A." é que você não tenha substituído o método ToString na B classe, você sombreada-lo usando a palavra-chave new. Por conseguinte, a classe B tem dois métodos ToString, uma herdada da A classe e um que sombras de TI. Se você usar uma referência A para chamar o método ToString, o método herdado é chamado, mas se você teria usado uma referência B chamá-lo, o método de sombreamento seria chamado, imprimindo "This is class B.".

Além disso, se você substituir o método ToString na B classe em vez de sombreamento-lo, seria imprimir "This is class B." independentemente do tipo da referência.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top