Кто может получить доступ к классу, объявленному как public?

Ответ

Класс с модификатором доступа public имеет наивысший уровень доступности. Это означает:

  • Внутри той же сборки (assembly): К нему можно обращаться из любого другого кода.
  • Из других сборок: Если на сборку, содержащую public класс, есть ссылка, то этот класс также доступен.
// AssemblyA.dll
namespace AssemblyA
{
    public class PublicLogger // Доступен отовсюду
    {
        public void Log(string message) => Console.WriteLine(message);
    }

    internal class InternalHelper // Доступен только внутри AssemblyA
    {
    }
}

// AssemblyB.csproj (имеет ссылку на AssemblyA)
using AssemblyA;

class ProgramInAssemblyB
{
    static void Main()
    {
        var logger = new PublicLogger(); // OK: класс public
        logger.Log("Hello from another assembly!");

        // var helper = new InternalHelper(); // ОШИБКА КОМПИЛЯЦИИ: InternalHelper internal
    }
}

Важные нюансы:

  1. Вложенные классы: Доступность вложенного класса ограничена областью видимости содержащего его класса. public вложенный класс будет доступен только если доступен его внешний класс.
  2. public vs internal: В рамках одной сборки поведение public и internal классов идентично. Ключевое различие проявляется при межсборочном доступе. internal — это стандартный выбор для служебных классов, которые не должны быть частью публичного API библиотеки.
  3. Доступ к членам класса: Даже если класс public, доступ к его полям, свойствам и методам регулируется их собственными модификаторами доступа (private, protected, internal, public).

Ответ 18+ 🔞

Ну, вот смотри, как это работает на практике, чтобы не было мухлежа. Класс с модификатором public — это как самый главный распиздяй на районе. Он везде свой, везде нужен, и ему похуй на границы.

Что это значит по-человечески?

  • Внутри своей же банды (сборки): Ему можно позвонить из любого переулка, с любого подъезда. Полный доступ.
  • Из соседнего района (другой сборки): Если ты знаешь, где эта банда тусуется (то есть добавил ссылку на сборку), то можешь спокойно подойти и начать с этим public классом работать. Как будто он и твой.

Вот, смотри на примере, как это выглядит в коде, а то одни слова:

// Это наша первая банда, AssemblyA.dll
namespace AssemblyA
{
    public class PublicLogger // Это наш публичный главарь. Виден всем.
    {
        public void Log(string message) => Console.WriteLine(message);
    }

    internal class InternalHelper // А это внутренний кореш. Только для своих.
    {
    }
}

// А это уже вторая банда, AssemblyB.csproj. Они знают, где первая тусуется (есть ссылка).
using AssemblyA;

class ProgramInAssemblyB
{
    static void Main()
    {
        var logger = new PublicLogger(); // Без проблем! Главаря видно издалека.
        logger.Log("Hello from another assembly!");

        // var helper = new InternalHelper(); // А вот это уже НИ-НИ. Ошибка компиляции! Это внутренний кореш, чужим его не показывают.
    }
}

А теперь три важных подводных камня, чтобы не обосраться:

  1. Вложенные классы — это как карманники у главаря. Даже если карманник (public вложенный класс) сам по себе публичный, но его шефа (внешний класс) посадили в каталажку (сделали private), то и к карманнику доступа не будет. Видимость вложенного упирается в видимость того, кто его содержит.

  2. public vs internal — главное различие. Внутри одной банды (сборки) между ними разницы нихуя нет, оба доступны. Вся соль — когда начинаешь торговать с другими районами. internal — это как внутренняя валюта, она работает только у нас. public — это доллары, ими можно расплатиться где угодно. Поэтому для всего служебного, что не должно светиться наружу, всегда юзай internal. Не засоряй публичное API.

  3. Доступ к членам — отдельная история. Допустим, ты пробился к публичному классу. Ура! Но это не значит, что тебе откроют все его комнаты. У каждого поля, свойства и метода есть свои собственные замки (private, protected и т.д.). Класс может быть public, но его метод — private. И что ты будешь делать? Стоять у закрытой двери и ебаться.