Какие модификаторы доступа можно применить к классу?

После небольшого исследования я определил, что единственными модификаторами доступа, которые можно применять к классам, являются:

  • общедоступный - доступен в любой сборке
  • внутренний - доступен только в текущей сборке.

но сообщение об ошибке ниже, похоже, подразумевает, что если класс не определен в пространстве имен, он может быть определен как private, protected или защищенный внутренний.

Являются ли публичные и внутренние модификаторы класса единственными модификаторами, которые вы можете использовать в классе, или есть другие?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test2343434
{
    class Program
    {
        static void Main(string[] args)
        {
            Tools.ToolManager toolManager = new Tools.ToolManager();

            Console.ReadLine();
        }
    }

}

namespace Tools
{
    //error: Elements defined in a namespace cannot be explicitly 
    //declared as private, protected, or protected internal
    private class ToolManager 
    {
        public ToolManager()
        {
            Console.WriteLine("inside tool manager");
        }
    }
}

person Edward Tanguay    schedule 21.07.2010    source источник


Ответы (4)


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

public class OuterClass
{
    private class PrivateNested {}
    protected class ProtectedNested {}
    protected internal class ProtectedInternalNested {}
    public class PublicNested {}
    internal class InternalNested {}
}

Обратите внимание, что вы не можете объявить тип, вложенный в struct, как protected или protected internal, потому что в этом нет никакого смысла :)

public struct OuterStruct
{
    private class PrivateNested {}
    public class PublicNested {}
    internal class InternalNested {}
}

C # не позволяет типам быть вложенными в интерфейсы (к сожалению, IMO - это было бы полезно для контрактов кода).

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

person Jon Skeet    schedule 21.07.2010
comment
Об этом определенно стоит знать, поскольку частные вложенные классы могут быть весьма полезными. - person Dan Bryant; 21.07.2010
comment
Ключевым моментом является то, что пространства имен являются не контейнерами, а классы являются контейнерами. Возможные модификаторы доступа определяются тем, находится ли он в контейнере (например, является ли класс членом или нет). - person Stephen Cleary; 21.07.2010
comment
@Stephen: пространства имен - это своего рода контейнеры: невложенные типы являются членами пространств имен. Из спецификации C #: Объявление-члена-пространства имен является либо объявлением-пространством имен (§9.2), либо объявлением типа (§9.6). - person Jon Skeet; 21.07.2010
comment
@Jon: В моей терминологии можно использовать слово «работа» - все хорошие имена уже заняты. :) Дело в том, что программисты часто попадают в ловушку, полагая, что пространство имен похоже на статический класс. Я считаю, что более правильным восприятием является то, что все типы верхнего уровня плоские, а пространство имен используется просто как префикс имени. Как только эта ментальная корректировка произведена, становится ослепляюще очевидным почему единственными возможными модификаторами доступа для типов верхнего уровня будут общедоступные и внутренние. - person Stephen Cleary; 21.07.2010

Взгляните на эту страницу MSDN:

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

Не имеет смысла делать объявление типа в пространстве имен чем-либо, кроме общедоступного для внешних сборок или внутреннего (C # не поддерживает концепцию дружественных классов или что-то в этом роде).

person Justin    schedule 21.07.2010

Ответ можно найти в уровнях доступности.

Класс «верхнего уровня», то есть не вложенный в другой класс, может быть только общедоступным или внутренним. По умолчанию (если вы ничего не декларируете) он внутренний.

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

person Daniel Rose    schedule 21.07.2010

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

person Brian Gideon    schedule 21.07.2010