Почему внутренняя защита не более строгая, чем внутренняя?

Я хочу создать внутреннее автоматическое свойство:

internal bool IP { get; protected internal set; }

Я думал, что можно сделать установщик protected или protected internal, но я всегда получаю сообщение об ошибке модификатор доступности должен быть более строгим, чем свойство. Разве это не так? Private мне тут не помогает.

РЕДАКТИРОВАТЬ:
Возникает вопрос: как реализовать автоматическое свойство с внутренним геттером и защищенным сеттером?


person tanascius    schedule 30.06.2009    source источник
comment
Ваша ошибка в том, что вы думаете о модификаторах как о возрастающих ограничениях. Фактически, модификаторы всегда уменьшают ограничения. Помните, что по умолчанию все является частным; только добавляя модификаторы, вы делаете их менее ограниченными.   -  person Eric Lippert    schedule 30.06.2009
comment
+1 - Эрик Липперт: ты всегда стараешься выразить это наилучшим образом   -  person JonH    schedule 07.01.2010
comment
Фактически, комбинация модификаторов уменьшает ограничения. Только установка модификатора действительно увеличивает ограничения, такие как public bool IP{get; private set;}   -  person Dani    schedule 09.07.2014


Ответы (8)


Фактически это protected или internal, а не и. Он доступен как производным классам и типам в одной сборке. Распространенное заблуждение - думать, что protected internal означает доступный только для производных классов в той же сборке.

person mmx    schedule 30.06.2009
comment
Хорошо, как мне сделать геттер внутренним, а сеттер защищенным? - person tanascius; 30.06.2009
comment
Вы не можете. Модификатор доступа к получателю / установщику должен быть правильным подмножеством модификатора доступа к свойству. - person mmx; 30.06.2009
comment
Моя проблема заключалась в неправильном понимании того, что защищенный внутренний означает защищенный И внутренний - спасибо, что указали на это. - person tanascius; 30.06.2009
comment
Я думаю, что ваша формулировка ОЧЕНЬ сбивает с толку. Использование AND и OR не помогает прояснить проблему. protected internal означает, что он доступен всем, у кого есть доступ protected, И всем, у кого есть доступ internal - person DevinB; 30.06.2009
comment
@devinb: Может быть, мое первое предложение. Но второе предложение проясняет проблему: он доступен как производным классам, так и типам в одной сборке. - person mmx; 30.06.2009
comment
Да, ты прав. Я имел в виду свою критику только к твоему первому предложению. - person DevinB; 30.06.2009

На уровне .NET есть два похожих, но разных уровня доступа:

  • FamilyAndAssembly: более строгий, чем защищенный или внутренний
  • FamilyOrAssembly: менее строгий, чем защищенный или внутренний

«защищенный внутренний» в C # означает FamilyOrAssembly; для FamilyAndAssembly нет модификатора.

Итак, ваш сеттер protected internal менее строг, чем общее свойство internal. Что вы могли бы сделать:

protected internal bool IP { internal get; set; }

Но тогда ваш сеттер менее ограничен, чем ваш геттер, что странно ...

Другая (несколько эквивалентная) альтернатива:

internal bool IP { get; set; }

protected void SetIP(bool ip)
{
    this.IP = ip;
}
person Jon Skeet    schedule 30.06.2009
comment
Хорошо, моим решением может быть внутреннее свойство только для чтения с защищенным резервным полем. - person tanascius; 30.06.2009
comment
Или ваша эквивалентная альтернатива с частным сеттером тоже подойдет. - person tanascius; 30.06.2009
comment
Мне приходит в голову (через несколько месяцев, конечно), что сеттер все еще доступен изнутри, что в некотором смысле менее ограничительно, чем защищено. Чтобы полностью сделать его внутренним геттером и защищенным сеттером, вам необходимо иметь защищенный void SetIP (значение типа bool) и внутренний bool GetIP (), а затем иметь частный bool _IP. - person DevinB; 28.09.2009
comment
Итак, вы только что сказали, что CLR имеет полный уровень ограничения доступа FamilyAndAssembly, который не используется в C # без использования магии IL и т. Д.? - person Chris Marisic; 02.05.2012
comment
@ChrisMarisic: Я не знаю, что произойдет, если вы попытаетесь его съесть. Это может быть похоже на некоторые запрещенные ограничения дженериков - компилятор C # будет подчиняться этому, но не дает никакого способа выразить это в вашем собственном коде. - person Jon Skeet; 02.05.2012
comment
@JonSkeet похоже на то, как вы не можете ограничить тип T перечислением обычно в C #? - person Chris Marisic; 02.05.2012
comment
@ChrisMarisic: Да, это именно тот пример, о котором я думал. - person Jon Skeet; 02.05.2012
comment
Начиная с C # 7.2, для FamilyAndAssembly доступен частный защищенный уровень доступности (см. stackoverflow.com/questions/22856215). - person Erlend Graff; 11.05.2018

Я бы счел это мошенничеством, поскольку Эрик Липперт сам находится в SO, но он написал отличное сообщение в блоге, в котором рассматривается эта проблема.

Почему я не могу получить доступ к защищенному члену из производного класса, часть третья

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

person DevinB    schedule 30.06.2009
comment
Это не обман. Обязательно размещайте ссылки. Это экономит мне время. - person Eric Lippert; 30.06.2009

Учитывая то, что упомянул Джон Скит (и комментарий пользователя 59808), не приведет ли это к желаемому результату?

protected internal bool IP { get; protected set; }

person void    schedule 08.12.2010
comment
Хотя выбранный ответ является более пояснительным, я бы хотел, чтобы этот ответ был включен в качестве того, что делать вместо этого. - person Mr. MonoChrome; 06.05.2015

protected internal менее строг, чем protected или internal, потому что он позволяет обоим его подклассам (protected) и чему-либо в той же сборке (internal) получить доступ к чему-либо.

person Powerlord    schedule 30.06.2009

защищенные внутренние средства, видимые для классов в той же сборке или для классов, производных от содержащего класса - другими словами, он виден тем, кто соответствует внутренним требованиям ИЛИ защищенным требованиям, а не И. Нет модификатора доступа, означающего защищенный И внутренний таким образом.

person David M    schedule 30.06.2009

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

person Brian Rudolph    schedule 30.06.2009

модификатор доступности должен быть более строгим, чем свойство

Internal является более строгим, чем защищенный: потому что защищенные объекты могут быть видны (подклассами) вне сборки.

Компилятор говорит, что нет смысла говорить, что set защищен (т.е. видим для подклассов вне сборки), когда все свойство IP является внутренним (т.е. невидимым вне сборки).

person ChrisW    schedule 30.06.2009