Что означает запланированный «закрытый защищенный» модификатор доступа C #?

133

Как часть документации Roslyn по GitHub, есть страница, которая называется Статус реализации функции языка. , с запланированными языковыми функциями для C # и VB.

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

private protected string GetId() {  } 

Существует также страница заметок по дизайну языка C # , на которой объясняется множество новых функций, но не эта.

Эрик Липперт сказал в комментарии :

Ваша ошибка в том, что вы считаете модификаторы возрастающими ограничениями. Модификаторы фактически всегда уменьшают ограничения. Помните, что по умолчанию все "личное"; только добавляя модификаторы, вы делаете их менее ограниченными.

В чем смысл private protected? Когда я могу использовать это?

Коби
источник
2
Обратите внимание, что информация об этом есть в примечаниях по дизайну языка VB .
Джесси Гуд
3
Это сопоставление с MethodAttributes.FamANDAssem. C # имеет странное отображение внутренних , он использует (Private | FamANDAssem). И внутренние защищенные карты (Private | Family). Атрибуты CLR странные.
Ганс Пассант
22
Эта предложенная функция сделает мой комментарий некорректным.
Эрик Липперт
Команда разработчиков C # опубликовала опрос с предлагаемым альтернативным синтаксисом для этой функции. Некоторые из них интересны, например protected & internal, assembly protectedили proternal(я надеюсь, что некоторые из них - шутки). Также есть ветка для обсуждения с некоторыми полезными идеями.
Коби
1
Функция теперь помечена как удаленная в статусе реализации языковой функции! Лично мне нравится идея этого уровня доступа, и я думаю, что это полезная функция. Я хочу использовать защищенный, чтобы сохранить мой код в соответствии с дизайном класса, но я не хочу, чтобы другие писали хакерские подклассы, которые получают доступ к этим членам. ИМО лучшее решение было бы, если бы мы могли написать protected | internalиprotected & internal
Феликс Кейл

Ответы:

98

Согласно « Professional C # 2008 » Де Билла Эвджена и Джея Глинна, страница 1699:

частная защита - «только производные типы в текущей сборке»

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

private protected-или- protected private- Участник защищен внутри сборки, но приватен вне сборки.

Gogutz
источник
72
Так что это «защищенный и внутренний» вместо «защищенный или внутренний»?
user541686
2
Будет ли теперь возможность иметь член, который доступен производным классам, принимать или возвращать объекты internalтипа, не требуя, чтобы член сам подвергался воздействию всего в сборке?
суперкат
Спасибо! Я не думал об этом. У меня есть случаи, когда я бы использовал этот модификатор и вернулся к нему 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 (и я вижу, вы обновили свой вопрос "теги").

Джепп Стиг Нильсен
источник
Это может быть только я, но стрелки, кажется, движутся в направлении «менее ограничительного, чем».
Acarlon
4
@acarlon Да, поэтому a → bна диаграмме означает « aболее ограничивающий, чем b», поэтому вы можете «прочитать» стрелку как «более ограничивающий, чем» (это я и пытался объяснить), поэтому стрелка указывает на наименее ограничивающий » направление». Кстати, противоположное соглашение для стрелок могло быть таким же хорошим, но мне пришлось выбрать одно соглашение.
Джеппе Стиг Нильсен
10

Это всего лишь предположение, но по названию вы можете догадаться, что это более ограниченная версия protected(или более расслабленная версия, privateесли хотите). И единственный разумный вариант - ограничение protectedповедения сборкой.

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

PS Он всегда существовал в CLR, но не в C # . Это комбинация protected и internal , цитата:

CLR также поддерживает тип доступа «Семья и сборка». Это означает, что метод доступен из объявленного типа, вложенного и производного типов, но только если они объявлены в одной сборке. Ну, очевидно, команда C # не думала об этом как о очень полезной функции, поэтому она не поддерживается на этом языке.

Петр Абдулин
источник
+1 за комментарий CLR - я трачу так много времени на C # и так мало на других языках .NET в эти дни, что я иногда забываю, что это не одно и то же.
Brichins
@DarrelHoffman спасибо, что заметили! Я немного перепутал здесь свои мысли)
Петр Абдулин
5

«Может быть» видно только подклассам, которые находятся в одной сборке. Это делает это немного ограниченным, чем protected.

Мехмет Аташ
источник
1

Смотрите спецификацию для "частной защиты":

Интуитивное значение private protected «доступно в этой сборке типами, производными от содержащего класса».

Жюльен Куврёр
источник