У чому сенс запланованого "приватного захищеного" модифікатора доступу C #?


133

Як частина документації Roslyn на GitHub, є сторінка під назвою Статус реалізації мовної функції із запланованими мовними функціями для C # та VB.

Однією з особливостей, яку я не міг обернути головою, був private protectedмодифікатор доступу:

private protected string GetId() {  } 

Також є сторінка C # Language Design Notes , яка пояснює багато нових функцій, але не цю.

Ерік Ліпперт сказав у коментарі :

Ваша помилка полягає в тому, що ви думаєте про модифікатори як про збільшення обмежень. Фактично модифікатори завжди зменшують обмеження. Пам'ятайте, що за замовчуванням речі є "приватними"; лише додаючи модифікатори, ви робите їх менш обмеженими.

У чому сенс private protected? Коли я можу ним користуватися?


2
Зверніть увагу, що інформація про неї міститься в примітках з дизайну мови VB .
Джессі Хороший

3
Це відображення до MethodAttributes.FamANDAssem. C # має дивне відображення внутрішнього , воно використовує (Private | FamANDAssem). І внутрішні захищені карти на (Приватне | Сімейне). Атрибути CLR дивні.
Ганс Пасант

22
Ця запропонована функція зробить мій коментар невірним.
Ерік Ліпперт

Команда дизайнерів C # опублікувала опитування із запропонованим альтернативним синтаксисом для цієї функції. Деякі з них цікаві, на кшталт protected & internal, assembly protectedабо proternal(сподіваюся, деякі з них - це жарти). Існує також тема дискусії з приємними уявленнями.
Кобі

1
Функція тепер позначена вилученою у статусі реалізації мовної функції! Особисто мені подобається ідея цього рівня доступу і я вважаю її корисною особливістю. Я хочу використовувати захищений, щоб зберегти свій код відповідно до дизайну класу, але я не хочу, щоб інші писали хакі підкласи, які отримують доступ до цих членів. ІМО найкращим рішенням було б, якби ми могли написати protected | internalіprotected & internal
Фелікс Кіль

Відповіді:


98

За матеріалами " Професійного C # 2008 " Де Білла Еввена та Джея Гліна, сторінка 1699:

приватний захищений - "лише похідні типи в межах поточної збірки"

C ++ / CLI має подібну функцію - Визначте та споживайте класи та структури (C ++ / CLI)> Видимість учасників :

private protected-or- protected private- Член захищений всередині зборів, але є приватним за межами асамблеї.


72
Так це "захищений і внутрішній" замість "захищений чи внутрішній"?
користувач541686

2
Чи зможе тепер член, доступний для похідних класів, приймати або повертати речі internalтипу, не вимагаючи, щоб член сам піддавався всьому в зборах?
supercat

Дякую! Я про це не думав. Насправді у мене є випадки, коли я б використав цей модифікатор і знову впав internal.
Кобі

3
Наявність цієї пропозиції / функції, схоже, internalговорить про те, що видимість (пов’язана з тим, де визначено клас) насправді є ортогональною для public/ protected/ privateвидимості (пов'язаної з успадкуванням) і, можливо, internalмає бути власним модифікатором, окремим від public/ protected/ private.
jpmc26

1
@jww - Я не дуже знайомий з Java, але настільки, наскільки я знаю, packageу Java більше схожий на простір імен у C #.
Гогуц

187

Ось всі модифікатори доступу в діаграмах Венна, від більш обмежувальних до більш розбещених:

private:
введіть тут опис зображення

private protected: - додано в C # 7.2
введіть тут опис зображення

internal:
введіть тут опис зображення

protected:
введіть тут опис зображення

protected internal:
введіть тут опис зображення

public:
введіть тут опис зображення


3
Вихідне зображення: Access Modifiers.pdn . Я використовував влучне ім’я Paint.Net .
Кобі

9
Де були ці діаграми все моє (C #) життя? Вони відмінні - дякую!
Джон Петерсон

28

Це лише для створення графіку (зробленого за допомогою http://ashitani.jp/gv/ ) різних рівнів доступності (зображення не вміщуються в коментарях).

діаграмна схема рівнів доступу на C #

Кожна стрілка означає "є більш обмежувальною, ніж".

Імена CLR є Private, FamilyANDAssembly, Assembly, Family, FamilyORAssembly, Public.


Набагато пізніше відредагуйте: виявився цей хороший новий рівень доступу (із справді поганим ім'ям) не врешті-решт включений до C # 6.0. Він підтримується лише з C # 7.2 (і я бачу, що ви оновили своє "теги").


Це може бути просто я, але, здається, стрілки йдуть у менш обмежувальному, ніж у напрямку.
акарлон

4
@acarlon Так, так що a → bна діаграмі означає " aє більш обмежувальним, ніж b", тому ви можете "прочитати" стрілку як "більш обмежувальну, ніж" (саме це я намагався пояснити), тому стрілка вказує на найменш обмежувальну " напрямок ». Протилежна умова для стрілок, до речі, могла бути так само хорошою, але мені довелося вибрати одну умову.
Джеппе Стіг Нільсен

10

Це лише здогадка, але з назви, можливо, можна здогадатися, що це більш обмежена версія protected(або більш спокійна версія, privateякщо ви хочете). І єдиний розумний варіант цього - обмеження protectedповедінки до складання.

Можливе використання: тоді ви хочете мати protectedвнутрішню реалізацію, але не для зовнішнього використання (і ви не хочете запечатувати клас).

PS Це завжди існувало в CLR, але не в C # . Це поєднання protected і internal , цитуйте:

CLR також підтримує тип доступу "Сім'я та збірка". Це означає, що метод доступний із типу декларування, вкладених та похідних типів, але лише у тому випадку, якщо вони оголошені в одній збірці. Ну, мабуть, команда C # не сприймала це як дуже корисну функцію, тому ця мова не підтримується.


+1 для коментаря CLR - я витрачаю стільки часу на C # і так мало в інших мовах .NET в ці дні, що іноді забуваю, що це не те саме.
бричін

@DarrelHoffman дякую, що помітили! Тут я трохи переплутав свої думки)
Петро Абдулін

5

"Може бути" видно лише для підкласів, які знаходяться в одній збірці. Це робить його трохи обмеженим, ніж protected.


1

Дивіться специфікацію функції "приватний захищений":

Інтуїтивне значення приватного захищеного "доступне в цій збірці за типами, що походять із класу, що містить".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.