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


Ответы:


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(...);

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, плюс все потомки также могут видеть метод.

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

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


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

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

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

15

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

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

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

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

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

11

Хм.

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

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

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

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

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

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

public class MyClass
{
    string s = "";
}

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

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

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


8

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

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


4

ммм ...

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

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


4

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

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

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


3

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

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


3

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

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


2

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


1

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

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

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

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

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

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

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

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

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.