ru
Feedback
C# | Вопросы собесов

C# | Вопросы собесов

Открыть в Telegram
5 049
Подписчики
+324 часа
-147 дней
-2630 день
Архив постов
Программист — лекарство от больных тимлидов, тупых багов и тех самых митов в 10 утра ☠️ Здесь собирают лучшие мемы про айтишников, чтобы спасти вашу психику от died'осов на работе. Идеально зачиллить вечерком и скинуть друзьям: @progeri

🤔 Что такое ООП? ООП (Объектно-Ориентированное Программирование) — это парадигма программирования, основанная на концепции объектов, которые объединяют данные и методы для их обработки. Основные принципы ООП включают инкапсуляцию, наследование, полиморфизм и абстракцию. ООП позволяет моделировать реальный мир с помощью классов и объектов, улучшая структуру и повторное использование кода. В C# все программы строятся на основе классов, что делает его строго объектно-ориентированным языком. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Какой сейчас последний C#? 🚩Нововведения 🟠Primary Constructors для классов и структур Позволяют определять конструкторы прямо в объявлении класса или структуры, что упрощает код и улучшает его читаемость.
public class Person(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;
}
🟠Collection Literals Обеспечивает более удобный синтаксис для создания коллекций.
var numbers = [1, 2, 3, 4, 5];
🟠Default Values для auto-properties Теперь можно задавать значения по умолчанию для auto-properties, что делает код более лаконичным.
public string Name { get; set; } = "Unknown";
🟠Using aliases Позволяет использовать алиасы для пространств имен, улучшая читаемость кода.
using Text = System.Text;
🟠Improved Lambda Expressions: Улучшены возможности для работы с лямбда-выражениями, делая их более гибкими и мощными. 🚩Зачем нужны эти изменения? Эти нововведения направлены на упрощение синтаксиса языка, улучшение читаемости и поддерживаемости кода, а также на повышение производительности и удобства разработки.
public class Program
{
    public static void Main()
    {
        var person = new Person("John", 30);
        Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");

        var numbers = [1, 2, 3, 4, 5];
        numbers.ForEach(n => Console.WriteLine(n));

        var name = new Name { Value = "Unknown" };
        Console.WriteLine(name.Value);
    }
}

public class Person(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;
}

public class Name
{
    public string Value { get; set; } = "Default Name";
}
Ставь 👍 и забирай 📚 Базу знаний

⚡️ Вся база знаний по IT в одном месте! 🧑‍💻 IT База — краткие разборы самого важного из мира IT. Сотни мастхев-ресурсов, каждый день новые материалы по работе и подготовке к собеседованиям. Подойдёт как новичкам, так и состоявшимся айтишникам; 🖥 Frontend База — всё для фронтенд разработчиков. Готовые решения для проектов, полезные курсы по JS/HTML/CSS, готовые роадмапы для комфортного освоения в профессии и дальнейшего развития; 👣 Backend База — самое важное для бэкендеров. Всё о работе с PHP, MySQL, MongoDB, Golang и Rust в одном месте, плюс полные курсы и лайфхаки для работы на каждый день; 🖥 База Знаний — склад полезных курсов и материалов, где легко найти что-то нужное по хэштегам. Если вам что-то интересно про IT, то оно уже лежит на Базе, проверяйте. Успей подписаться, чтобы не потерять!

🤔 Когда инициируется сборка мусора? Сборка мусора в C# инициируется автоматически, когда система обнаруживает, что недостаточно доступной памяти или при достижении порогов работы сборщика. Также она может быть запущена вручную с помощью метода `GC.Collect()`. Garbage collector удаляет объекты, которые больше не используются программой, освобождая память. Сборка мусора помогает предотвратить утечки памяти и поддерживает эффективность приложения. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое сайт машина? Это концепция из теории автоматов и программирования, которая описывает поведение системы на основе различных состояний и переходов между ними. Она позволяет моделировать сложные системы и процессы, управляя переходами между разными состояниями в зависимости от входных данных или событий. 🚩Зачем нужна 🟠Упрощения логики программы Позволяет разбить сложную логику на более простые, управляемые состояния. 🟠Четкого определения поведения системы Описывает, как система реагирует на различные события. 🟠Улучшения читабельности и поддержки кода Легче понять и изменить поведение системы, когда оно описано в виде состояний и переходов. 🚩Как используется 🟠Игровую разработку Для управления поведением персонажей. 🟠Системы управления В промышленной автоматике. 🟠Разработку пользовательских интерфейсов Для управления состояниями интерфейсов и переходами между ними. 🟠Протоколы связи Для управления последовательностью сообщений и реакцией на них.
using System;

public enum TrafficLightState
{
    Red,
    Green,
    Yellow
}

public class TrafficLight
{
    private TrafficLightState _state;

    public TrafficLight()
    {
        _state = TrafficLightState.Red;
    }

    public void ChangeState()
    {
        switch (_state)
        {
            case TrafficLightState.Red:
                _state = TrafficLightState.Green;
                break;
            case TrafficLightState.Green:
                _state = TrafficLightState.Yellow;
                break;
            case TrafficLightState.Yellow:
                _state = TrafficLightState.Red;
                break;
        }
        Console.WriteLine($"Состояние светофора: {_state}");
    }
}

class Program
{
    static void Main()
    {
        TrafficLight trafficLight = new TrafficLight();
        trafficLight.ChangeState(); // Состояние светофора: Green
        trafficLight.ChangeState(); // Состояние светофора: Yellow
        trafficLight.ChangeState(); // Состояние светофора: Red
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое лямбда выражения в С#? Лямбда-выражения — это анонимные функции, которые используются для создания кратких методов или делегатов в C#. Они упрощают работу с LINQ, коллекциями и обратными вызовами. Лямбда-выражения могут захватывать переменные из своей области видимости, делая их удобным способом для создания замыканий. Используются для упрощения и улучшения читаемости кода. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Какие бывают типы? Существует несколько типов данных, которые можно разделить на основные категории: простые типы, ссылочные типы, и пользовательские типы. 🚩Основные типы данных: 🟠Простые типы (Value Types) Простые типы хранят значения непосредственно и включают примитивные типы, перечисления и структуры. 🟠Примитивные типы Целочисленные типы: byte (8-битный, от 0 до 255) sbyte (8-битный, от -128 до 127) short (16-битный, от -32,768 до 32,767) ushort (16-битный, от 0 до 65,535) int (32-битный, от -2,147,483,648 до 2,147,483,647) uint (32-битный, от 0 до 4,294,967,295) long (64-битный, от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807) ulong (64-битный, от 0 до 18,446,744,073,709,551,615) 🟠Типы с плавающей запятой: float (32-битный, ±1.5e−45 до ±3.4e38, 7 знаков точности) double (64-битный, ±5.0e−324 до ±1.7e308, 15-16 знаков точности) 🟠Десятичные типы: decimal (128-битный, ±1.0 × 10−28 до ±7.9 × 10^28, 28-29 знаков точности) 🟠Прочие простые типы: char (16-битный символ Unicode) bool (логический тип, принимает значения true или false) 🟠Структуры и перечисления Структуры (struct): Пользовательские типы данных, которые являются значимыми типами и могут содержать поля, методы, свойства и т.д. Перечисления (enum): Тип, представляющий набор именованных констант. 🟠Ссылочные типы (Reference Types) Ссылочные типы хранят ссылку на область памяти, где находятся данные. К ним относятся классы, интерфейсы, делегаты и массивы. 🚩Классы и интерфейсы 🟠Классы (class): Основной строительный блок объектно-ориентированного программирования, могут содержать поля, методы, свойства, события и т.д. 🟠Интерфейсы (interface): Контракты, определяющие набор методов и свойств, которые должны быть реализованы классами. 🚩Делегаты и события 🟠Делегаты (delegate): Типы, представляющие ссылку на методы. Используются для реализации обратных вызовов и событий. 🟠События (event): Механизм, через который объекты могут сообщать о произошедших действиях. 🚩Массивы и строки 🟠Массивы (Array): Коллекции элементов одного типа, доступ к которым осуществляется по индексу. 🟠Строки (string): Неизменяемые последовательности символов. 🚩Пользовательские типы Пользовательские типы могут быть созданы на основе простых и ссылочных типов. 🚩Кортежи и анонимные типы 🟠Кортежи (Tuple): Группировка значений различных типов. 🟠Анонимные типы: Типы, созданные для хранения наборов значений, определённых на лету. 🟠Nullable-типы Позволяют значимым типам принимать значение null.
int? nullableInt = null; // Nullable int
Пример использования простых типов:
int age = 30;
double salary = 50000.50;
bool isEmployed = true;
char grade = 'A';
Пример использования классов и интерфейсов:
public interface IAnimal
{
    void Speak();
}

public class Dog : IAnimal
{
    public void Speak()
    {
        Console.WriteLine("Bark");
    }
}
Пример использования структуры:
public struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}
Пример использования перечисления:
public enum DaysOfWeek
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое middleware в ASP.NET core? Middleware — это компоненты, которые обрабатывают HTTP-запросы и ответы в ASP.NET Core. Каждый компонент middleware может либо обработать запрос, либо передать его следующему компоненту в конвейере. Они используются для выполнения задач, таких как аутентификация, логирование или обработка ошибок. Последовательность middleware определяет поведение приложения и порядок обработки запросов. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Расскажи про принцип подстановки Барбары Лисков? Принцип подстановки Барбары Лисков (Liskov Substitution Principle, LSP) является одним из пяти принципов объектно-ориентированного программирования, известных под акронимом SOLID. 🚩Основная идея LSP Основная идея заключается в том, что если класс B является подтипом класса A, то объекты класса A могут быть заменены объектами класса B без изменения правильности работы программы. Это означает, что наследование должно использоваться так, чтобы производный класс сохранял поведение базового класса. 🚩Правила для соблюдения LSP 🟠Сохранение контрактов: Производный класс должен соблюдать контракт, определённый базовым классом. Это включает в себя сигнатуры методов и ожидания (предусловия и постусловия). 🟠Инварианты класса: Инварианты, или неизменяемые условия, которые выполняются для объектов базового класса, должны оставаться в силе и для объектов производного класса. 🟠Постусловия не должны быть ослаблены: Производный класс не должен ослаблять постусловия методов базового класса. Постусловия - это условия, которые гарантированы после выполнения метода. 🟠Предусловия не должны быть усилены: Производный класс не должен усиливать предусловия методов базового класса. Предусловия - это условия, которые должны быть выполнены перед вызовом метода. В этом примере Penguin нарушает LSP, так как он не может летать. Если заменить экземпляр FlyingBird на Penguin, программа перестанет работать правильно.
public abstract class Bird
{
    public abstract void Fly();
}

public class FlyingBird : Bird
{
    public override void Fly()
    {
        Console.WriteLine("I can fly!");
    }
}

public class Penguin : Bird
{
    public override void Fly()
    {
        throw new NotSupportedException("Penguins cannot fly.");
    }
}
Теперь классы FlyingBird и Penguin оба наследуют класс Bird и реализуют метод Move, но каждый делает это по-своему, не нарушая LSP.
public abstract class Bird
{
    public abstract void Move();
}

public class FlyingBird : Bird
{
    public override void Move()
    {
        Fly();
    }

    private void Fly()
    {
        Console.WriteLine("I can fly!");
    }
}

public class Penguin : Bird
{
    public override void Move()
    {
        Console.WriteLine("I waddle.");
    }
}
🚩ПлюсыПовышенная гибкость и расширяемость: Код, который соблюдает LSP, легче модифицировать и расширять без риска нарушения существующей функциональности. ➕Упрощённое тестирование: Код, соответствующий LSP, легче тестировать, так как можно заменять объекты их подтипами в тестах без изменения поведения. ➕Повышенная поддерживаемость: Такой код легче поддерживать и рефакторить, так как контракт между базовым и производным классами чётко определён и соблюдается. Ставь 👍 и забирай 📚 Базу знаний

Если ты Junior .NET разработчик и хочешь выйти на новый уровень 📈 — время прокачать навыки с Level Up! Приглашаем на бесплат
Если ты Junior .NET разработчик и хочешь выйти на новый уровень 📈 — время прокачать навыки с Level Up! Приглашаем на бесплатный live coding практикум «Разработка системы учёта проездных билетов за 60 минут» с преподавателем курса 18 октября в 19:00 МСК. 💡 Что узнаете: Инструменты разработки на .NET. Как создать веб-приложение на C# и интегрировать его с базой Postgres. 📅 Заявка на практикум

🤔 Что такое делегат? Делегат в C# — это тип, который представляет ссылки на методы с определённой сигнатурой. Делегаты используются для передачи методов в качестве параметров и для обратных вызовов (callbacks). Они являются основой для событий и лямбда-выражений в C#. Делегаты позволяют вызывать методы динамически, что делает код более гибким. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое полиморфизм подтипов? Полиморфизм подтипов — это способность объектов разных классов, связанных отношениями наследования, обрабатываться единообразно. Это позволяет использовать объекты подклассов через ссылки на базовые классы, что делает код гибким и расширяемым. 🚩Основные понятия 🟠Наследование: Классы могут наследовать другие классы, унаследуя их методы и свойства. 🟠Интерфейсы: Классы могут реализовывать интерфейсы, обеспечивая конкретную реализацию методов интерфейса. 🟠Виртуальные методы: Методы, объявленные как virtual в базовом классе, могут быть переопределены в производных классах с использованием ключевого слова override. 🟠Позднее связывание: Метод, который будет вызван, определяется во время выполнения, а не во время компиляции. Базовый класс и производные классы
public class Animal
{
    // Виртуальный метод, который может быть переопределен в производных классах
    public virtual void Speak()
    {
        Console.WriteLine("Animal speaks");
    }
}

public class Dog : Animal
{
    // Переопределение метода Speak для класса Dog
    public override void Speak()
    {
        Console.WriteLine("Dog barks");
    }
}

public class Cat : Animal
{
    // Переопределение метода Speak для класса Cat
    public override void Speak()
    {
        Console.WriteLine("Cat meows");
    }
}
Использование полиморфизма подтипов
class Program
{
    static void Main()
    {
        // Создание массива объектов типа Animal
        Animal[] animals = new Animal[]
        {
            new Dog(),
            new Cat(),
            new Animal()
        };

        // Вызов метода Speak для каждого объекта в массиве
        foreach (Animal animal in animals)
        {
            animal.Speak();
        }
    }
}
🟠Полиморфизм с интерфейсами Полиморфизм также может быть достигнут через интерфейсы. В этом примере классы Dog и Cat реализуют интерфейс IAnimal, и метод Speak вызывается через интерфейс, что также демонстрирует полиморфизм подтипов.
public interface IAnimal
{
    void Speak();
}

public class Dog : IAnimal
{
    public void Speak()
    {
        Console.WriteLine("Dog barks");
    }
}

public class Cat : IAnimal
{
    public void Speak()
    {
        Console.WriteLine("Cat meows");
    }
}

class Program
{
    static void Main()
    {
        IAnimal[] animals = new IAnimal[]
        {
            new Dog(),
            new Cat()
        };

        foreach (IAnimal animal in animals)
        {
            animal.Speak();
        }
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое принципы SOLID? SOLID — это набор пяти принципов объектно-ориентированного программирования, которые помогают писать гибкий и поддерживаемый код. Принципы включают: Single Responsibility (одна ответственность), Open/Closed (открытость для расширения, закрытость для изменений), Liskov Substitution (подстановка Барбары Лисков), Interface Segregation (разделение интерфейсов) и Dependency Inversion (инверсия зависимостей). Эти принципы помогают избежать излишней сложности и улучшить структуру программного кода. Применение SOLID делает код более устойчивым к изменениям и легче в сопровождении. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое статический полиморфизм? Статический полиморфизм, также известный как полиморфизм на этапе компиляции, — это форма полиморфизма, при которой вызов метода или доступ к члену определяется во время компиляции, а не во время выполнения. Статический полиморфизм достигается с помощью таких механизмов, как перегрузка методов (method overloading) и обобщенные типы (generics). 🚩Перегрузка методов (Method Overloading) Перегрузка методов позволяет иметь несколько методов с одинаковым именем, но разными параметрами (различные типы, количество или порядок параметров). Компилятор решает, какой метод вызвать, основываясь на переданных аргументах.
public class MathOperations
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }

    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }
}

class Program
{
    static void Main()
    {
        MathOperations math = new MathOperations();
        
        int result1 = math.Add(2, 3);         // Вызовется метод Add(int, int)
        double result2 = math.Add(2.5, 3.5);  // Вызовется метод Add(double, double)
        int result3 = math.Add(1, 2, 3);      // Вызовется метод Add(int, int, int)
        
        Console.WriteLine(result1);  // Вывод: 5
        Console.WriteLine(result2);  // Вывод: 6.0
        Console.WriteLine(result3);  // Вывод: 6
    }
}
🚩Обобщенные типы (Generics) Обобщенные типы позволяют создавать классы, методы и структуры, работающие с любыми типами данных, обеспечивая безопасность типов на этапе компиляции и избегая затрат на приведение типов.
public class GenericCalculator<T>
{
    public T Add(T a, T b)
    {
        dynamic da = a;
        dynamic db = b;
        return da + db;
    }
}

class Program
{
    static void Main()
    {
        GenericCalculator<int> intCalculator = new GenericCalculator<int>();
        int intResult = intCalculator.Add(3, 4); // Вызов метода для типа int
        Console.WriteLine(intResult); // Вывод: 7

        GenericCalculator<double> doubleCalculator = new GenericCalculator<double>();
        double doubleResult = doubleCalculator.Add(2.5, 3.7); // Вызов метода для типа double
        Console.WriteLine(doubleResult); // Вывод: 6.2
    }
}
🚩Отличия от динамического полиморфизма 🟠Статический полиморфизм определяется на этапе компиляции, в то время как динамический полиморфизм (также известный как позднее связывание или полиморфизм на этапе выполнения) определяется во время выполнения с помощью виртуальных методов и наследования. В этом примере компилятор не знает заранее, какой метод Speak будет вызван, так как это определяется во время выполнения.
public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("Animal speaks");
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Dog barks");
    }
}

class Program
{
    static void Main()
    {
        Animal myAnimal = new Dog();
        myAnimal.Speak(); // Вывод: Dog barks
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое Inversion of control и dependency injection? Inversion of control (IoC) — это принцип, при котором управление созданием объектов передается внешним компонентам. Dependency injection (DI) — это один из способов реализации IoC, когда зависимости передаются объекту через конструктор, методы или свойства. Это позволяет улучшить тестируемость и модульность кода. DI делает систему более гибкой, позволяя изменять реализации зависимостей без изменения кода. Ставь 👍 и забирай 📚 Базу знаний

Обучаем Java-разработчиков оплата после выхода на работу В Kata Academy можно выучиться на Java-разработчика бесплатно, а зап
Обучаем Java-разработчиков оплата после выхода на работу В Kata Academy можно выучиться на Java-разработчика бесплатно, а заплатить уже после трудоустройства по специальности из фактической зарплаты. Если задуматься, то все в выигрыше: — ты получаешь работу в Москве или Санкт-Петербурге с хорошей зарплатой, мы получаем процент за инвестиции в тебя; — в наших интересах научить тебя так, чтобы твоя зарплата была как можно выше; — мы прокачиваем твои навыки еще 2 года после курса: проводим выездные мероприятия и мастер-классы — и доходы наших выпускников растут; — мы не зависим от банков и их рассрочек — кризис не повлиял на доступность курсов. Чтобы попасть на курс, нужно выполнить небольшое тестовое задание. Переходи по ссылке и оставляй заявку! Узнать больше #реклама 16+ kata.academy О рекламодателе

🤔 Как работает static конструктор? Статический конструктор в предназначен для инициализации статических членов класса или для выполнения действий, которые должны быть выполнены один раз для всего класса, а не для каждого его экземпляра. 🚩Основные характеристики 🟠Автоматический вызов: Статический конструктор вызывается автоматически перед первым использованием любого статического члена класса или перед созданием первого экземпляра класса, в зависимости от того, что произойдет раньше. 🟠Единовременное выполнение: Статический конструктор выполняется только один раз на весь период существования приложения. 🟠Без параметров: Статический конструктор не может принимать параметры. 🟠Невозможность явного вызова: Невозможно вызвать статический конструктор вручную. Он вызывается автоматически. Рассмотрим класс, который использует статический конструктор для инициализации статического поля:
public class ConfigurationManager
{
    public static string Configuration;

    // Статический конструктор
    static ConfigurationManager()
    {
        Configuration = "Default Configuration";
        Console.WriteLine("Статический конструктор выполнен.");
    }
}

class Program
{
    static void Main()
    {
        // Обращение к статическому полю вызывает статический конструктор
        Console.WriteLine(ConfigurationManager.Configuration);
        
        // Создание экземпляра класса не вызовет статический конструктор снова
        ConfigurationManager configManager = new ConfigurationManager();
        Console.WriteLine(ConfigurationManager.Configuration);
    }
}
1⃣Первое обращение к статическому члену: Когда программа впервые обращается к ConfigurationManager.Configuration, вызывается статический конструктор класса ConfigurationManager. 2⃣Инициализация: Внутри статического конструктора происходит инициализация статического поля Configuration. 3⃣Вывод: В консоли будет выведено сообщение "Статический конструктор выполнен." и значение "Default Configuration". Ставь 👍 и забирай 📚 Базу знаний

🤔 В чём разница абстрактного класса и интерфейса? Абстрактный класс может содержать как реализацию методов, так и абстрактные методы, а интерфейс — только определения методов без реализации. Абстрактные классы могут иметь поля и конструкторы, а интерфейсы — нет. Класс может наследовать только один абстрактный класс, но реализовать несколько интерфейсов. Интерфейсы предоставляют более гибкий способ организации контракта для классов. Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое static? Static - это ключевое слово, которое используется для объявления статических членов в классе. Статические члены принадлежат самому классу, а не его экземплярам. 🚩Основные моменты использования 🟠Поля Статические поля объявляются с использованием ключевого слова static и принадлежат классу в целом. Все экземпляры класса разделяют одно и то же статическое поле.
public class Example
{
     public static int Counter;
}

// Доступ к статическому полю
Example.Counter = 10;
Console.WriteLine(Example.Counter); // Выведет 10
🟠Методы Статические методы могут быть вызваны без создания экземпляра класса. Статические методы могут обращаться только к другим статическим членам класса.
public class Calculator
{
    public static int Add(int a, int b)
    {
        return a + b;
    }
}

// Вызов статического метода
int sum = Calculator.Add(5, 3);
Console.WriteLine(sum); // Выведет 8
🟠Свойства Статические свойства похожи на статические поля, но с доступом через методы get и set.
public class Configuration
{
    private static string _setting;

    public static string Setting
    {
        get { return _setting; }
        set { _setting = value; }
    }
}

// Доступ к статическому свойству
Configuration.Setting = "My Setting";
Console.WriteLine(Configuration.Setting); // Выведет "My Setting"
🟠Конструкторы Статические конструкторы используются для инициализации статических членов класса. Они вызываются один раз при первом обращении к статическим членам.
public class Database
{
    public static string ConnectionString;

    static Database()
    {
        ConnectionString = "Initial Catalog=myDatabase;Data Source=myServer;";
    }
}

// При первом доступе вызывается статический конструктор
Console.WriteLine(Database.ConnectionString); // Выведет строку подключения
🚩Зачем нужен? 🟠Общие данные и функции: Статические члены полезны для хранения данных или функций, которые должны быть общими для всех экземпляров класса. 🟠Упрощение доступа: Позволяет вызывать методы и свойства без необходимости создавать экземпляр класса. 🟠Инициализация ресурсов: Статические конструкторы полезны для инициализации ресурсов или настройки параметров, необходимых для работы класса. 🚩Ограничения 🟠Статические методы не могут обращаться к нестатическим членам напрямую, так как у них нет доступа к экземпляру класса. 🟠Статические конструкторы не могут иметь параметры и вызываются автоматически при первом обращении к классу. Ставь 👍 и забирай 📚 Базу знаний