¿Cuál es la verdadera razón para impedir el acceso de miembros protegidos a través de una clase base / hermanos?

Recientemente descubrí que un método en una clase derivada solo puede acceder a los miembros de la instancia protegida de la clase base a través de una instancia de la clase derivada (o una de sus subclases):

class Base
{
    protected virtual void Member() { }
}

class MyDerived : Base
{
    // error CS1540
    void Test(Base b) { b.Member(); }
    // error CS1540
    void Test(YourDerived yd) { yd.Member(); }

    // OK
    void Test(MyDerived md) { md.Member(); }
    // OK
    void Test(MySuperDerived msd) { msd.Member(); }
}

class MySuperDerived : MyDerived { }

class YourDerived : Base { }

Logré evitar esta restricción agregando un método estático a la clase base, ya que los métodos de Base tienen acceso a Base.Member, y MyDerived puede llamar a ese método estático.

Sin embargo, todavía no entiendo la razón de esta limitación. He visto un par de explicaciones diferentes, pero no explican por qué MyDerived.Test () todavía puede acceder a MySuperDerived.Member.

La explicación del principio:'Protegido' significa que solo es accesible para esa clase y sus subclases. YourDerivedpodría anular Member (), creando un nuevo método que solo debería ser accesible para YourDerived y sus subclases. MyDerived no puede llamar al yd.Member () anulado porque no es una subclase de YourDerived, y no puede llamar a b.Member () porque b podría ser una instancia de YourDerived.

OK, pero entonces ¿por qué MyDerived puede llamar a msd.Member ()? MySuperDerived podría anular Member (), y esa anulación solo debería ser accesible para MySuperDerived y sus subclases, ¿verdad?

Realmente no sabes hasta el tiempo de ejecución si estás llamando a un miembro anulado o no. Y cuando el miembro es un campo, no se puede anular de todos modos, pero el acceso todavía está prohibido.

La explicación pragmática:Otras clases podrían agregar invariantes que su clase no conoce, y usted debe usar su interfaz pública para que puedan mantener esos invariantes. Si MyDerived pudiera acceder directamente a los miembros protegidos de YourDerived, podría romper esos invariantes.

Mi misma objeción se aplica aquí. MyDerived tampoco sabe qué pueden agregar las invariantes MySuperDerived (puede ser definido en un ensamblaje diferente por un autor diferente). ¿Por qué MyDerived puede acceder directamente a sus miembros protegidos?

Me da la impresión de que esta limitación de tiempo de compilación existe como un intento equivocado de resolver un problema que realmente solo puede resolverse en tiempo de ejecución. Pero tal vez me esté perdiendo algo. ¿Alguien tiene un ejemplo de un problema que podría ser causado al permitir que MyDerived acceda a los miembros protegidos de la Base a través de una variable de tipo YourDerived o Base, perono ¿Ya existen al acceder a ellos a través de una variable de tipo MyDerived o MySuperDerived?

-

ACTUALIZACIÓN: Sé que el compilador está simplemente siguiendo la especificación del lenguaje; Lo que quiero saber es el propósito de esa parte de la especificación. Una respuesta ideal sería: "Si MyDerived pudiera llamar a YourDerived.Member (), $ NIGHTMARE pasaría, pero eso no puede suceder cuando se llama a MySuperDerived.Member () porque $ ITSALLGOOD".

Respuestas a la pregunta(6)

Su respuesta a la pregunta