В C # в чем разница между публичным, приватным, защищенным и не имеющим модификатора доступа?

728

Все мои студенческие годы я использую public, и хотел бы знать разницу между public, privateи protected?

И что же staticделать, а не иметь ничего?

мили относительного движения
источник

Ответы:

1008

Модификаторы доступа

От docs.microsoft.com :

public

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

private

Тип или член могут быть доступны только с помощью кода в том же классе или структуре.

protected

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

private protected (добавлено в C # 7.2)

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

internal

Доступ к типу или элементу может получить любой код в той же сборке, но не из другой сборки.

protected internal

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

Когда модификатор доступа не установлен, используется модификатор доступа по умолчанию. Так что всегда есть какая-то форма модификатора доступа, даже если она не установлена.

static модификатор

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

Статический класс в основном такой же, как и нестатический класс, но есть одно отличие: статический класс не может быть создан внешне. Другими словами, вы не можете использовать ключевое слово new для создания переменной типа класса. Поскольку нет переменной экземпляра, вы получаете доступ к членам статического класса, используя само имя класса.

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

static class Foo()
{
    static Foo()
    {
        Bar = "fubar";
    }

    public static string Bar { get; set; }
}

Статические классы часто используются как сервисы, вы можете использовать их так:

MyStaticClass.ServiceMethod(...);
mbillard
источник
17
И у вас могут быть статические методы в нестатических классах, верно?
Джон Бубриски
14
Да, они будут вести себя так же, как в моем примере.
Мбиллард
7
Что означает термин «собрание» в этом контексте?
Джонатан Глисон
1
@gotoVoid Все, что вы искали в Google, неверно. Согласно MSDN , защищенный внутренний означает, что «к типу или члену может обращаться любой код в сборке, в которой он объявлен, или из производного класса в другой сборке».
Кевин
2
В чем разница между Защищенным и Частным Защищенным? Для меня это звучит так же ..
goofyui
161

Графический обзор (краткое содержание)

видимость

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



Для значений по умолчанию, если вы не указали модификатор доступа, смотрите здесь:
Видимость по умолчанию для классов и членов C # (поля, методы и т. Д.)?

Невложенных

enum                              public
non-nested classes / structs      internal
interfaces                        internal
delegates in namespace            internal
class/struct member(s)            private
delegates nested in class/struct  private

Вложенные:

nested enum      public
nested interface public
nested class     private
nested struct    private

Также есть ключевое слово sealed, которое делает класс не наследуемым.
Кроме того, в VB.NET ключевые слова иногда отличаются, поэтому здесь есть шпаргалка:

VB против CS эквивалентов

Стефан Штайгер
источник
1
@ ᴀʀᴜn BᴇrtiL: Ты уверен? Производный класс в другой сборке?
Стефан Штайгер
Производный класс в одной сборке мы можем, разные мы не можем. Я думал, что вы имели в виду, как в той же сборке ...
Арун Бертиль
1
@ ᴀʀᴜn BᴇrtiL: Хм, верно, это действительно должно быть заштриховано.
Стефан Штайгер
1
Я думаю, что есть ошибка в диаграмме. Если для класса используется internal, класс может быть получен другим классом в той же сборке. Кроме того, если для свойства используется внутренний модификатор, к этому свойству можно также получить доступ в производном классе в той же сборке. Возможно, диаграмма верна, потому что есть «да» в разделе «содержащий сборку», но это может быть неправильно понято, потому что есть «нет» в «производных классах».
Ах.
160

Public - если вы видите класс, то вы можете увидеть метод

Приватный - если вы являетесь частью класса, вы можете увидеть метод, в противном случае нет.

Защищено - То же, что и Private, плюс все потомки также могут видеть метод.

Статический (класс) - Помните различие между «Классом» и «Объектом»? Забудь обо всем этом. Они одинаковы со «статическим» ... класс является единственным экземпляром самого себя.

Статический (метод) - всякий раз, когда вы используете этот метод, он будет иметь систему координат, независимую от фактического экземпляра класса, частью которого он является.

JosephStyons
источник
1
Разве вы не можете иметь статические методы в нестатическом классе?
Джон Бубриски
1
Да, но я говорил о статическом классе. Я добавил отдельную запись для описания статических методов. Спасибо за улов.
JosephStyons
2
«Объект» может не подходить для разговора о C #, поскольку базовый тип для всех классов - System.Object . «Экземпляр» будет лучшим словом или «объектом» (строчная буква «О»).
Lesderid
@lesderid 'object' - это псевдоним 'System.Object', использование которого также может сбивать с толку. «экземпляр» был бы лучше, я думаю :)
dpp
Те же правила применяются к структурам.
gsharp
35

Репостить потрясающие диаграммы из этого ответа .

Вот все модификаторы доступа на диаграммах Венна, от более ограниченных до более беспорядочных:

private:
введите описание изображения здесь

private protected: - добавлено в C # 7.2
введите описание изображения здесь

internal:
введите описание изображения здесь

protected:
введите описание изображения здесь

protected internal:
введите описание изображения здесь

public:
введите описание изображения здесь

Павел
источник
24

введите описание изображения здесь

using System;

namespace ClassLibrary1
{
    public class SameAssemblyBaseClass
    {
        public string publicVariable = "public";
        protected string protectedVariable = "protected";
        protected internal string protected_InternalVariable = "protected internal";
        internal string internalVariable = "internal";
        private string privateVariable = "private";
        public void test()
        {
            // OK
            Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(publicVariable);

            // OK
            Console.WriteLine(protectedVariable);

            // OK
            Console.WriteLine(internalVariable);

            // OK
            Console.WriteLine(protected_InternalVariable);
        }
    }

    public class SameAssemblyDerivedClass : SameAssemblyBaseClass
    {
        public void test()
        {
            SameAssemblyDerivedClass p = new SameAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }

    public class SameAssemblyDifferentClass
    {
        public SameAssemblyDifferentClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // NOT OK
            // Console.WriteLine(privateVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            //Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }
}

 using System;
        using ClassLibrary1;
        namespace ConsoleApplication4

{
    class DifferentAssemblyClass
    {
        public DifferentAssemblyClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            // Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protectedVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protected_InternalVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protected_InternalVariable);
        }
    }

    class DifferentAssemblyDerivedClass : SameAssemblyBaseClass
    {
        static void Main(string[] args)
        {
            DifferentAssemblyDerivedClass p = new DifferentAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            //Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);

            SameAssemblyDerivedClass dd = new SameAssemblyDerivedClass();
            dd.test();
        }
    }
}
Нароттам Гоял
источник
1
Я не вижу, что этот ответ добавляет ко многим другим ответам за последние пять лет.
Джон Сондерс
4
Это просто простое объяснение. Поскольку другие ответы немного запутаны и наполовину ответили :)
Нароттам Гоял
4
@John Saunders: Различает разделение видимости производного класса между этим классом, находящимся в одном и том же классе, и другим классом, находящимся в другой сборке. Кроме того, он сообщает, как он получил эту информацию, показывая свой пример кода. Так что это фактически добавляет к другим ответам. Его некромантия, вероятно, была вызвана моим комментарием в моем ответе.
Стефан Штайгер
2
«Производный класс в другой сборке» - это добавляет значение к диаграмме, уже приведенной в другом ответе. Разница полезна, особенно в случае «защищенного внутреннего»
Нирман
Я считаю эту диаграмму самой легкой для понимания. Чтобы сохранить этот текущий (с C # 7.2), добавить Private Protected, это будет: тот же класс = Yes, та же сборка, производный класс = Yes, та же сборка, любой класс = NO, другая сборка, производный класс = NO, другая сборка, любой класс = NO. Еще одно дополнительное предложение также состоит в том, чтобы не менять порядок слов для protected internal, так как это ломает пневмонию от ответа @ user1810087
Intrastellar Explorer
22

По вопросу Ничего

  • Типы пространства имен по умолчанию являются внутренними
  • Любой член типа, включая вложенные типы, по умолчанию являются закрытыми
leppie
источник
15

Еще один визуальный подход текущего модификатора доступа (C # 7.2). Надеемся, что схема поможет запомнить ее проще
(нажмите на изображение для интерактивного просмотра.)

интерактивные модификаторы доступа svg

Снаружи внутри

Если вам трудно вспомнить модификаторы доступа с двумя адресами, запомните это снаружи .

  • частная защита : частная снаружи (та же сборка) внутренняя защита (та же сборка)
  • защищенный внутренний : защищенный снаружи (тот же узел) внутренний внутри (такой же узел)
user1810087
источник
11

Хм.

Смотрите здесь: Access Modifiers .

В двух словах:

Public дает методу или типу полную видимость из других типов / классов.

Private разрешает только типу, содержащему приватный метод / переменную, доступ к приватному методу / переменной (обратите внимание, что вложенные классы также имеют доступ к содержащим классам приватных методов / переменных).

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

«Ничто» - это эквивалент VB.NET нулю. Хотя если вы имеете в виду «ничего», означающее «нет модификатора доступа», то это зависит, хотя очень грубое практическое правило (безусловно, в C #) заключается в том, что если вы не укажете явно модификатор доступа, метод / переменная объявление обычно настолько ограничено, насколько это возможно. т.е.

public class MyClass
{
    string s = "";
}

эффективно так же, как:

public class MyClass
{
    private string s = "";
}

Связанная статья MSDN предложит полное описание, когда явно не указан модификатор доступа.

CraigTP
источник
8

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

Ничто не походит на ноль, но в VB.
Статический означает, что у вас есть один экземпляр этого объекта, метод для каждого экземпляра этого класса.

Тони
источник
4

ммм ...

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

Вы можете получить доступ непосредственно из определения класса.

gbianchi
источник
4

Статус Private указывает, что переменные могут быть доступны только объектам одного класса. Защищенный статус расширяет этот доступ и для включения потомков класса.

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

Проверьте MSDN ссылку для получения дополнительной информации

Грант Худ
источник
3

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

Статические члены - один на класс, а не один на экземпляр.

jpfollenius
источник
3

Внимательно следите за вашей доступностью ваших занятий. Публичные и защищенные классы и методы по умолчанию доступны для всех.

Кроме того, Microsoft не очень хорошо демонстрирует модификаторы доступа (общедоступные, защищенные и т. Д. Ключевые слова) при создании новых классов в Visual Studio. Так что будьте внимательны и подумайте о своей доступности для своего класса, потому что это дверь для ваших внутренних возможностей реализации.

Патрик Питерс
источник
2

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

Дариус Кучинскас
источник
1

C # имеет всего 6 модификаторов доступа:

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

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

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

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

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

C # 7.2 добавляет новый уровень доступности:

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

Исходный код, содержащий пример кода нового модификатора защищенного доступа

ягодный
источник
0

Все описания модификаторов доступа для C #

введите описание изображения здесь

ОСШ
источник