Каково происхождение CS0060: Прямой базовый класс типа класса должен быть по крайней мере таким же доступным, как и сам тип класса
Я просто столкнулся с этим основным правилом наследования в.net:
CS0060: Прямой базовый класс типа класса должен быть по крайней мере таким же доступным, как и сам тип класса
Мне любопытно, почему это правило было разработано.
Кто-нибудь знает, почему этот вид наследования предпочтительнее? Есть ли языки, которые делают это по-другому.
// CS0060.cs
class MyClass
// try the following line instead
// public class MyClass
{
}
public class MyClass2 : MyClass // CS0060
{
public static void Main()
{
}
}
Спасибо
5 ответов
Мне любопытно, почему это правило было разработано. Кто-нибудь знает, почему этот вид наследования предпочтительнее? Есть ли языки, которые делают это по-другому?
На второй вопрос ответить гораздо проще, чем на первый. Да, другие языки делают это по-другому. В частности, C++ допускает " частное наследование"; то есть отношение наследования становится частной реализацией класса. Если бы C# имел частное наследование, то очевидно, что базовый класс мог бы быть менее доступным, чем производный класс. Но C# не имеет частного наследования.
На первый вопрос трудно ответить, потому что вопросы "почему" изначально плохо подходят для переполнения стека. Единственный правильный ответ на вопрос "почему было разработано это правило?" это потому, что комитет по проектированию языков решил, что это лучший компромисс, если дать много конкурирующих целей дизайна.
Это, вероятно, не удовлетворительный ответ. Для правильного ответа на этот вопрос потребуется не просто перечислить все эти цели проектирования и их относительные достоинства, но также описать психическое состояние каждого члена команды разработчиков на момент принятия решения, а также описание того, каким процессом различные конфликты возникшие были решены. Это решение было принято тринадцать лет назад, так что тропа действительно очень холодная.
Я не был в этой комнате в тот день тринадцать лет назад, но я могу дать вам некоторое представление о факторах, которые комитет по проектированию должен был бы учитывать при принятии решения о разрешении частного наследования:
- Влияние на "концептуальный счет". (Сколько связанных понятий должен понимать пользователь, чтобы правильно использовать эту функцию? Сколько новых понятий эта функция добавляет к языку?)
- Сходство или отличие функции от C++, что может быть полезным или запутанным.
- Успех функции в C++. Люди используют это в C++? Они правильно его используют? Каждый ли пользователь C++ понимает эту функцию достаточно хорошо, чтобы сделать правильный выбор?
- Количество взаимодействия с другими языковыми функциями. Такая функция может изменить поиск имени и разрешение перегрузки потенциально тонкими или запутанными способами.
- Уровень соответствия с родственными языковыми особенностями. (Интерфейсы могут быть менее доступными.)
- Сложность реализации.
- И еще много факторов.
Поскольку у меня нет трех или четырех свободных часов, мне понадобилось бы написать подробный анализ всех этих факторов для этой функции, а затем попытаться задним числом психоаналитически проанализировать команду разработчиков, я думаю, что у вас будет жить со своим неосуществленным любопытством.
Я рекомендую не задавать подобные вопросы на Stack Overflow в будущем. Попробуйте придерживаться конкретных технических вопросов о реальном коде, которые имеют точные ответы.
class BaseClass {...}
public class MyClass: BaseClass {...} // Error
http://msdn.microsoft.com/en-us/library/cx03xt0t.aspx
Это упомянуто в спецификации языка C#, и это также имеет смысл, поскольку в вашем случае публичный класс можно использовать в "публичном" контексте с публичным уровнем доступности, обеспечивающим доступ к непубличному классу, который является вашим базовым классом, и это быть неправильным поведением.
Согласно спецификации языка C# 5.0:
(Загрузите спецификацию с http://www.microsoft.com/en-us/download/details.aspx?id=7029).
Существуют следующие ограничения доступности:
• Прямой базовый класс типа класса должен быть по крайней мере таким же доступным, как и сам тип класса.
• Явные базовые интерфейсы типа интерфейса должны быть как минимум такими же доступными, как и сам тип интерфейса.
• Возвращаемый тип и типы параметров типа делегата должны быть по крайней мере такими же доступными, как и сам тип делегата.
• Тип константы должен быть как минимум таким же доступным, как и сама константа.
• Тип поля должен быть как минимум таким же доступным, как и само поле.
• Тип возвращаемого значения и типы параметров метода должны быть как минимум такими же доступными, как и сам метод.
• Тип свойства должен быть как минимум таким же доступным, как и само свойство.
• Тип события должен быть как минимум таким же доступным, как и само событие.
• Тип и типы параметров индексатора должны быть как минимум такими же доступными, как и сам индексатор.
• Тип возврата и типы параметров оператора должны быть как минимум такими же доступными, как и сам оператор.
• Типы параметров конструктора экземпляра должны быть по крайней мере такими же доступными, как и сам конструктор экземпляра.
Все последующие классы должны иметь по крайней мере такую же доступность, что и MyClass2 в вашем примере.
Это логично, отсюда и следующий пример.
Если у вас есть внутренний класс A с открытым свойством с именем Prop. Как, по вашему мнению, внешний мир узнает, что ваш производный открытый класс B имеет свойство Prop, если базовый класс также не является общедоступным?
Я понимаю вашу точку зрения, @mohammed sameeh. Какова ценность этого? Или каковы будут побочные эффекты, если.net будет вести себя иначе, если попытается разрешить это?
@ Anirudh добирался до этого, когда говорил о безопасности этого базового класса.
Если бы у вас не было этого ограничения, модель безопасности, состоящая в том, чтобы постоянно скрывать "личные"/"внутренние" вещи, могла бы быть нарушена - или очень запутанно!
Это действительно самый большой потенциальный побочный эффект, неправильно выставляющий свойства и методы.
Поскольку дочерний класс по определению наследует свойства и методы родителя, как их следует учитывать в этом случае?
Вместо того, чтобы иметь (даже больше) правил о том, как свойства и методы предоставляются в наследовании и подклассах, .net упрощает работу, поддерживая иерархию представления и применяя ее.
У кого-то еще есть крутое замечание о том, что произойдет с приведением типов или тому подобным без ограничений.
Конечно, могут существовать и другие правила. Может быть интересно увидеть другой язык, который делает это по-другому.
Но наверняка нам нужны какие-то правила, поэтому, когда кто-то еще потребляет ваш класс или сборку, вы знаете, чего ожидать.
class MyClass
{
}
public class MyClass2 : MyClass // CS0060
{
public static void Main()
{
}
}
Причины этой ошибки связаны с тем, что MyClass не является общедоступным, поэтому вам нужно, чтобы он был общедоступным, просто добавьте
public
перед
class MyClass