Почему C # не поддерживает пересечение защищенной и внутренней доступности? - PullRequest
17 голосов
/ 23 января 2012

внутренняя защита:

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

CLR имеет концепцию пересечения из защищенного и внутреннего доступа, но C # не поддерживает это.

Итак, мой вопрос:

В чем смысл опускать этот Модификатор доступа , есть ли конкретная причина? Так почему же C # не должен его поддерживать?

Ответы [ 7 ]

7 голосов
/ 23 января 2012

Обновление: C # 7.2 вводит это с помощью модификатора доступа private protected, который в некоторых отношениях кажется неправильным, но не допускает большой части путаницы, которую я опишу ниже, поэтому, возможно, является лучшей из плохой связки.

Лично я хотел этого несколько раз. Бывают случаи, когда в сборке выставляется класс и один или несколько классов, производных от него, как public, и бывают случаи, когда некоторый член базового класса используется только этими производными классами и не должен подвергаться воздействию защищенных классов. в других сборках (довольно часто конструктор, чтобы вообще не иметь классов, производных от него в других сборках).

Конечно, всегда полезно определять ваш доступ как можно более ограничительно, и поэтому пересечение защищенного и внутреннего - именно то, что здесь необходимо.

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

Однако рассмотрим обратную сторону.

В действительности существует некоторая путаница в том, как protected internal дает объединение protected и internal. Это, вероятно, самый неправильно понятый доступ, судя по вопросам на таких сайтах, как этот.

Как мы должны это назвать? internal protected? Вы можете себе представить, как часто люди путают это с protected internal? Мы бы хотели что-то более четко дифференцированное, и мы хотели бы того же для internal protected (потому что мы все еще увеличили его вероятность путаницы). Это не проблема, на которую нужно ответить, но уменьшение количества ключевых слов также является хорошей идеей.

Даже если будет найден идеальный ответ на вопрос об именах, вероятность путаницы при введении еще одного уровня доступа не будет полностью побеждена.

Итак, помня об этом, давайте снова посмотрим на рост. Нам больше не нужно ломать голову, когда нам это нужно, используя internal, уменьшая количество ошибок, вызванных неправильным использованием такого члена. Хорошо, как часто это происходит, и насколько вероятны такие ошибки на самом деле? Не очень часто и не очень вероятно.

Таким образом, в то время как я действительно время от времени желаю, чтобы C # имел это, минутная пауза обычно заставляет меня радоваться, что они этого не сделали.

6 голосов
/ 23 января 2012

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

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

Тем не менее, я не нашел бы неразумным, чтобы это было разрешено в C #.Самодисциплина часто оказывается полезной;это причина, по которой разработчики языка различают private и internal, несмотря на то, что они одинаковы для внешних потребителей.

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

3 голосов
/ 23 января 2012

Это было дизайнерское решение, но рассмотрим, что оно означает:

  • , доступный только для производных классов в той же сборке.

Это не очень полезная граница, я не могу придумать четкого варианта использования.
И вот почему, вероятно, не стоило придумывать новое ключевое слово (-combination).

Я бы скорее спросил, почему CLR поддерживает это.Ортогональность я полагаю.

2 голосов
/ 10 мая 2013

Я хотел задать этот же вопрос, но, к счастью, ТАК нашел этот для меня.

Я могу понять точку зрения, что для этого потребуется, по крайней мере, новое ключевое слово или новая семантика для существующих ключевых слов, поэтому оно не поддерживается, поскольку экономическая выгода не работает в его пользу.

Однако я подвергаю сомнению, законно ли избегать реализации этой функции CLR из-за узкого варианта использования или потому, что это может смутить людей.

Один из аргументов, приведенных выше, заключается в том, что он используется только для обеспечения самодисциплины.

Но то же самое можно сказать и о любом модификаторе видимости, который не public. Идея о том, что это применимо только к «одному разработчику из одной библиотеки», также явно ошибочна. Многие библиотеки разрабатываются группами людей, и для разработчика внутри этой команды вполне естественно добавить члена, который он или она хотел бы ограничить только внутренними типами, производными от его или ее базы.

Тогда есть такой сценарий:

internal class Foo {

}

public class PublicBase {
  protected Foo MyFoo { get; set; }
}

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

В этой ситуации я застрял: я не могу использовать protected и не могу использовать protected internal.

Вместо этого я должен использовать internal, который неправильно передает другим членам моей команды, что его следует использовать из кода вне класса. Конечно, я могу добавить комментарий (и даже прикрепить EditorBrowsableAttribute из Never к нему, но это также скрыло бы его от внутренних наследников) - но это не то же самое.

На самом деле, единственный способ добиться этого - взломать сборку с помощью перезаписи IL после сборки, но мне нужна эта видимость (или ее отсутствие) во время компиляции, а не после сборки.

В конечном счете, аргументы о "какие ключевые слова будут использоваться" или " как это будет реализовано " для меня не имеют значения: я программист, а не Дизайнер языка C #.

Точно так же я должен сказать, что аргументы типа «Ну, protected internal достаточно запутанный для многих» также не имеют значения. Есть так много разработчиков, с которыми я общался, лично или виртуально, которые не понимают такие вещи, как ?: или общие ограничения - угадайте, что они не используют их! Это не значит, что я не должен.

Так что да, я понимаю причины, по которым он не реализован - но я с ними не согласен - поэтому мой ответ о том, почему C # не поддерживает его, заключается в том, что дизайнеры C # ошиблись.

И да, я готов к теплу, которое может привести к моей двери:)

2 голосов
/ 23 января 2012

Так почему же C # не должен его поддерживать?

Неправильный вопрос.Вопрос должен звучать так: «Почему должен C # поддерживать protected and internal

Имейте в виду, что естественным состоянием функции является реализация , а не .Реализация функции является очень дорогой с точки зрения ресурсов, тестирования и, давайте не будем забывать, альтернативной стоимости (то есть она вытесняет другие функции).Таким образом, чтобы преодолеть эти затраты, было бы лучше иметь чрезвычайно четкое преимущество для реализации функции, которая преодолевает эти затраты.

В частности, каково значение protected and internal?На самом деле нет веской причины ограничивать доступ только к производным классам в одной сборке.

IMO Странно, что CLR это поддерживает, но это так.Это не значит, что C # нужно.

0 голосов
/ 23 января 2012

Вы всегда можете сделать:

public MyExternallySealedClass
{
     internal MyExternallySealedClass() {...}

     ...
}

До тех пор, пока вы не позволите ни одному внешнему потребителю создать экземпляр объекта, что вас волнует, если он попытается получить его?Короткий ответ: запрашиваемая вами функция не приносит ничего нового, и у вас уже есть инструменты для выполнения того, что вы запрашиваете.

0 голосов
/ 23 января 2012

Насколько я знаю, вы можете использовать пересечение модификаторов защищенного и внутреннего доступа, но не с той интерпретацией, которую вы хотите (возможно, из-за того, что сказал Хенк):

  1. Защищено: доступ к типу или члену возможен только с помощью кода в том же классе или структуре или в производном классе.

  2. Внутренний: доступ к типу или элементу возможен из любого кода в той же сборке, но не из другой сборки.

  3. Защищенный внутренний: доступ к типу или элементу может быть осуществлен любым кодом в той же сборке или любым производным классом в другой сборке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...