переопределение защищенного внутреннего с защищенным!


Это extension для этого Вопрос спросил час назад.

Мы не можем изменить access modifiers, когда переопределяем virtual method в derived классе. Рассмотрим класс Control в пространстве имен System.Web.UI

public class Control : IComponent, IDisposable,...
{ 
   protected internal virtual void CreateChildControls()
   { }
   .
   .
}

Теперь Рассмотрим Это

public class someClass : System.Web.UI.Control
    { 
       // This should not compile but it does
        protected override void CreateChildControls()
        { }

       // This should compile but it does not
        protected internal override void CreateChildControls()
        { }  
    }
Может ли какой-либо орган объяснить это ? Спасибо
3 26

3 ответа:

Мы не можем изменять модификаторы доступа при переопределении виртуального метода в производном классе.

Это утверждение ложно. Вы можете и должны изменить модификаторы доступа, когда они находятся в точно описанной ситуации. В других ситуациях вы не должны изменять модификаторы доступа.

Я отсылаю вас к разделу 10.6.4 спецификации, который гласит:

Переопределенное объявление не может быть изменено доступность виртуального метод. Однако, если переопределенный базовый метод защищен внутренним и он объявлен в другой ассамблее чем собрание, содержащее способ переопределить затем переопределить объявленная доступность метода должна будьте защищены.

Рассуждение простое.

У тебя, Асад, есть банковский счет, BankAccount.

У тебя есть дом. Вы сдаете комнату в доме своему лучшему другу Чарли.

У Чарли есть сын Дэвид, который живет в квартире.

Ты у меня есть сын Элрой, который живет в кондоминиуме.

У Элроя есть сын, твой внук Фрэнк, который живет в юрте. У Элроя есть лучший друг Грег, который живет с ним в одной квартире. Вы предоставляете доступ к вашему банковскому счету самому себе, всем, кто живет в доме, и любому из ваших потомков. Итак, люди, которые могут получить доступ к банковскому счету, - это Асад, Чарли, Элрой и Фрэнк. Давид не получает доступа, потому что он не является ни вами, ни вашим потомком, ни живет в нем. Дом. То, что он ребенок вашего соседа по дому, не имеет значения; он не получает доступа к вашему банковскому счету. Грег также не получает доступа к вашему банковскому счету. Он не твой потомок. Он не живет в доме. Тот факт, что он живет с вашим потомком, не дает ему тех же прав, что и вашему потомку. Теперь мы подходим к сути дела. Элрой не имеет права предоставлять доступ к вашему банковскому счету Грегу. Вы владеете этим банковским счетом, и вы сказали: "я сам, мои потомки и мои соседи по дому". Ваши дети не имеют права расширять доступность банковского счета за пределы того, что вы изначально создали. Когда Элрой описывает, какой доступ он имеет к банковскому счету, ему разрешается только сказать: "я предоставляю доступ к этому себе и моим потомкам", потому что это то, что вы уже разрешили. Он не может сказать: "я предоставляю доступ к банковскому счету себе, моим потомкам и другим жителям Кондо".

Просто для ясности:

  • I и мои потомки получают доступ = защищенный доступ
  • я и мои соседи по дому получаем доступ = внутренний доступ
  • я и мои потомки и мои соседи по дому получаем доступ = защищенный внутренний доступ
  • Control = Asad
  • CreateChildControls = BankAccount
  • Дом = Система.Сеть.DLL
  • Чарли = любой тип в системе.Сеть.DLL
  • Дэвид = производный тип Чарли в монтажной квартире.DLL
  • Элрой = someClass
  • Кондо = ваша сборка содержащий SomeClass
  • Грег = какой-то другой класс в кондоминиуме.DLL
  • Франк = производный тип некоторого класса в юрте.DLL
  • Юрта = какое-то другое собрание

Потому что, хотя терминология различна, переопределение ее как protected сохраняет видимость члена той же самой. Если бы вам было разрешено переопределить его как protected internal, то вы бы внезапно предоставили член любому другому типу в вашей сборке.

Защищенный внутренний означает защищенный или внутренний. Таким образом, если при переопределении вне исходной сборки вам было разрешено пометить ее защищенной внутренней, вы позволяли бы другим классам в той же сборке, что и переопределитель, вызывать этот метод. Это фактически означало бы, что внутренняя инкапсуляция исходного родителя будет нарушена.