¿Por qué una clase C # puede heredar de una interfaz tanto implícita como explícitamente?

StackOverflow https://stackoverflow.com/questions/253058

Pregunta

Hoy encuentro que una clase C # puede heredar una interfaz tanto de manera implícita como explícita. Esto me sorprende Si C # funciona de esta manera, una instancia puede comportarse de manera diferente cuando se hace referencia de manera diferente.

interface IFoo
{
    void DoSomething();
}

class Foo : IFoo
{
    #region IFoo Members
    public void DoSomething()
    {
        Console.WriteLine("do something implicitly");
    }
    #endregion

    #region IFoo Members
    void IFoo.DoSomething()
    {
        Console.WriteLine("do something explicitly");
    }
    #endregion
}


        Foo f = new Foo();
        f.DoSomething();

        ((IFoo)f).DoSomething();

El código anterior se ejecuta y genera

do something implicitly
do something explicitly

Creo que este diseño de C # hace inconsistencia de comportamiento. Quizás sea obligatorio que una clase C # pueda heredar de una interfaz de manera implícita o explícita, pero no ambas.

¿Hay alguna razón por la cual C # está diseñado de tal manera?

¿Fue útil?

Solución

Su ejemplo no implementa IFoo tanto implícita como explícitamente. Solo implementa IFoo.DoSometing () explícitamente. Tienes un nuevo método en tu clase llamado DoSomething (). No tiene nada que ver con IFoo.DoSomething, excepto que tiene el mismo nombre y parámetros.

Otros consejos

Cada clase que implementa una interfaz tiene una asignación entre los miembros de esa clase y los miembros de la interfaz. Si la clase explícitamente implementa un miembro de interfaz, entonces la implementación explícita siempre se asignará a la interfaz. Si no hay una implementación explícita, se espera una implementación implícita, que se asignará a la interfaz.

Cuando una clase tiene el mismo nombre de miembro y tipos asociados que una interfaz pero también implementa explícitamente el miembro correspondiente para la interfaz, entonces la clase " implícita " la implementación no se considera una implementación de la interfaz en absoluto (a menos que la implementación explícita lo llame).

Además de los diferentes significados en cada caso donde la clase implementa múltiples interfaces con el mismo nombre / tipo de miembro, incluso con una sola interfaz, se considera que la clase misma tiene una interfaz implícita que podría tienen los mismos miembros / tipos que la única interfaz pero aún significan algo diferente.

Esto lo hace más flexible para cuando hay colisiones. En particular, mire IEnumerator y IEnumerator<T> - ambos tienen una propiedad Current, pero de diferentes tipos . Tiene que utilizar la implementación de interfaz explícita para implementar ambos (y el formulario genérico extiende el formulario no genérico).

Herencia múltiple: ¿Qué sucede si deriva de dos interfaces que definen el mismo método para diferentes propósitos?

  interface IMoveable
  {
    public void Act();
  }

  interface IRollable
  {
    public void Act();
  }

  class Thing : IMoveable, IRollable
  {
    //TODO Roll/Move code here

    void IRollable.Act()
    {
      Roll();
    }

    void IMoveable.Act()
    {
      Move();
    }
  }

Chicos, gracias por sus respuestas.

Resulta que " la clase C # puede heredar una interfaz de manera implícita y explícita al mismo tiempo " Es en realidad una ilusión. En realidad, una clase puede heredar una interfaz por una vez.

En la pregunta original, el " DoSomething " el método parece " implícitamente implementa " interfaz IFoo (el método es realmente generado por VS2008), pero en realidad NO lo es. Con la implementación explícita de la interfaz IFoo, el & Quot; DoSomething & Quot; el método se convierte en un método normal que no tiene nada que ver con IFoo excepto con la misma firma.

Todavía creo que es un diseño complicado de C #, y es fácil de usar por error. Digamos que tengo un código como este

        Foo f = new Foo();
        f.DoSomething();

Ahora, quiero refactorizarlo al siguiente código. Parece perfectamente correcto, pero el resultado de la ejecución es diferente.

        Action<IFoo> func = foo => foo.DoSomething();
        func(f);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top