Jaki jest prawdziwy powód uniemożliwiania dostępu chronionym członkom przez klasę bazową / rodzeństwa?

Niedawno odkryłem, że metoda w klasie pochodnej może uzyskać dostęp tylko do chronionych elementów instancji klasy bazowej za pośrednictwem instancji klasy pochodnej (lub jednej z jej podklas):

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 { }

Udało mi się obejść to ograniczenie, dodając metodę statyczną do klasy bazowej, ponieważ metody Base mają dostęp do Base.Member, a MyDerived może wywołać tę metodę statyczną.

Nadal jednak nie rozumiem przyczyny tego ograniczenia. Widziałem kilka różnych wyjaśnień, ale nie wyjaśniają, dlaczego MyDerived.Test () nadal ma dostęp do MySuperDerived.Member.

Wyjaśnienie zasadnicze:„Chroniony” oznacza, że ​​jest dostępny tylko dla tej klasy i jej podklas. YourDerivedmógłby przesłonić Member (), tworząc nową metodę, która powinna być dostępna tylko dla YourDerived i jej podklas. MyDerived nie może wywołać przesłoniętego yd.Member (), ponieważ nie jest to podklasa YourDerived, i nie może wywołać b.Member (), ponieważ b może być w rzeczywistości instancją YourDerived.

OK, ale dlaczego MyDerived może wywołać msd.Member ()? MySuperDerived może przesłonić Member (), a to nadpisanie powinno być dostępne tylko dla MySuperDerived i jego podklas, prawda?

Naprawdę nie wiesz do czasu wykonania, czy dzwonisz do zastępowanego członka, czy nie. A kiedy członek jest polem, nie można go już przesłonić, ale dostęp jest nadal zabroniony.

Pragmatyczne wyjaśnienie:Inne klasy mogą dodawać niezmienniki, o których twoja klasa nie wie, i musisz użyć ich publicznego interfejsu, aby mogli utrzymać te niezmienniki. Jeśli MyDerived może uzyskać bezpośredni dostęp do chronionych członków YourDerived, może złamać te niezmienniki.

Mam tutaj ten sam sprzeciw. MyDerived nie wie, jakie niezmienniki może dodać MySuperDerived - może być zdefiniowane w innym zestawie przez innego autora - dlaczego więc MyDerived może uzyskać bezpośredni dostęp do chronionych członków?

Mam wrażenie, że to ograniczenie czasu kompilacji istnieje jako błędna próba rozwiązania problemu, który naprawdę można rozwiązać tylko w czasie wykonywania. Ale może coś mi brakuje. Czy ktoś ma przykład problemu, który mógłby zostać spowodowany przez udostępnienie MyDerived dostępu do chronionych elementów Base przez zmienną typu YourDerived lub Base, ale nienie istnieje już podczas uzyskiwania dostępu do nich za pomocą zmiennej typu MyDerived lub MySuperDerived?

-

UPDATE: Wiem, że kompilator postępuje zgodnie ze specyfikacją języka; chcę wiedzieć, jaki jest cel tej części specyfikacji. Idealna odpowiedź brzmiałaby następująco: „Gdyby MyDerived mogło wywołać YourDerived.Member (), wydarzyłoby się $ NIGHTMARE, ale to nie może się zdarzyć podczas wywoływania MySuperDerived.Member () ponieważ $ ITSALLGOOD.”

questionAnswers(6)

yourAnswerToTheQuestion