Pregunta

Salida:
B-> Hola! desde explícita.

¿No debería ser:?
A-> Hola! desde explícita.

¿Por qué el yeso no explícita (IHello) una llamada IHello.Hello () de la clase 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();
    }
}
¿Fue útil?

Solución

No, no debería.

La llamada a Hello es equivalente a la comentada, uno - la ruta a conseguir una IHello no importa (a menos que requiera la ejecución en tiempo de cheques o conversión); el tipo en tiempo de compilación es sólo IHello de cualquier manera, y la asignación de interfaz es la misma, sin embargo de llegar allí.

Cuando una interfaz se implementa explícitamente más de una vez en la jerarquía de tipos, se utiliza la aplicación en el tipo más derivada. (Cuando se llama a través de la interfaz.)

Desde la sección 13.4.4 de la Especificación C # 3.0:

  

mapeo de interfaz para una clase o   struct C localiza una implementación para   cada miembro de cada interfaz   especificado en la lista de la clase base de C.   La implementación de un particular,   miembro i.m. interfaz, donde I es la   interfaz en la que el miembro de M es   declarada, se determina mediante el examen   cada clase o estructura S, a partir de   C y repitiendo para cada sucesiva   clase base de C, hasta que un partido es   Ubicado:

     
      
  • Si S contiene una declaración   de un miembro de interfaz explícita   aplicación que coincide I y H,   a continuación, esta persona es la implementación   de i.m.
  •   
  • En caso contrario, si S contiene una declaración de un miembro del público no estático que coincide M, entonces esta persona es la aplicación de mensajería instantánea Si más de un miembro de partidos, que no se especifica qué miembro es la aplicación de mensajería instantánea Esta situación sólo puede ocurrir si S es un tipo construido donde los dos miembros de los declarados en el tipo genérico tienen diferentes firmas, pero los argumentos de tipo hacen sus firmas idénticas.
  •   

Otros consejos

(A) un no hace nada. La referencia ya está declarada como una manera echándola a A no tendrá ningún efecto.

A pesar de que su referencia se declara como A, el objeto al cual se refiere es de tipo B. Si lanzas este objeto para IHello, una llamada a Hola () llamará aplicación explícita objeto de B de Hola.

La salida es exactamente como se esperaba.

No, cuando se crea un nueva Método (ToString), no es virtual. Nueva simplemente significa que no le importa que "ocultar" la versión de la clase base - por lo que si usted lo llama con una referencia que ha echado a un tipo específico (A), se ejecuta el método en la clase A, sin tener en cuenta el tipo real del objeto que está llamando. (Es decir, que llamó A.ToString () por lo que ejecutó A.ToString ())

Cuando se crea un método virtual, a continuación, independientemente de qué tipo lanzas se utiliza la referencia a la aplicación del tipo real del objeto (es decir, que ha creado un B, por lo que cuando llamaste (cualquiera que sea el objeto es) .Hello, se llama B.Hello)

La diferencia fundamental es que una llamada es virtual y el otro no lo es.

No, no debería.

Cuando se llama a un método virtual, no importa lo que el tipo de la referencia es. El método que se llama se determina por el tipo real del objeto, no el tipo de la referencia.

A medida que crea una instancia de la clase B, el tipo real del objeto es B. La razón por la que se imprime "This is class A." es que no se haya anulado el método ToString en el B clase, que ha ensombrecido usando la palabra clave new. Por lo tanto la clase B tiene dos métodos ToString, uno heredado de la clase A y uno que sombras ella. Si se utiliza una referencia A para llamar al método ToString, se llama al método heredado, pero si hubiera utilizado una referencia B llamarlo, el método de sombreado se llamaría, la impresión de "This is class B.".

Además, si reemplaza el método ToString en el B clase en lugar de sombra, sería imprimir "This is class B." independientemente del tipo de la referencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top