Skip to content
L-SYSTEM

recommendedintermediate

C# 14 and .NET 10: From Surface Knowledge to Working Knowledge (Extended)

For developers who "know C#" but stall at code review and in interviews when asked why something is built the way it is. The language is taught not as a list of constructs but as a set of decisions with a price: value and reference types, memory and the garbage collector, equality, null, pattern matching, strings and Span, generics, collections, LINQ, exceptions, async and concurrency, data at the process boundary, reflection and source generators. Five units then take SOLID one principle at a time, each as the answer to a concrete pain rather than a slogan. Design patterns follow — creational, structural, behavioural and the applied .NET ones — always including the case where the pattern hurts. The course closes on testability, talking through an architecture decision out loud, and what is new in C# 13 and 14. An optional branch, "C# in an application", takes the language into a working service: the host and DI, Minimal APIs, HttpClient and background jobs, EF Core, tests, and deployment to Azure. Every example lives in one system, the ENGAGE backend of the fictional firm Aldervane. Targets C# 14 / .NET 10 LTS. Written in Russian.

Path through the course

· 38 units

the order is free · the steps below are the order the author suggests, not a conditionView: map · steps

28

Span, Memory, ref struct и как мерить

~2 h

by the author’s design, after any one of these: “Значимые и ссылочные типы: стек, куча и упаковка”, “Строки: неизменяемость, интернирование, StringBuilder, Span”

25

Прикладные паттерны .NET: Repository, Options, CQRS, Result

~2 h

by the author’s design, after 2 of these: “Порождающие паттерны: кто и как создаёт объекты”, “Структурные паттерны: как собирать объекты в целое”, “Поведенческие паттерны: кто кого вызывает и когда”

36 · C# в приложении

EF Core без иллюзий

~2 h

by the author’s design, after “Хост, DI на практике, конфигурация, логирование”, “LINQ: отложенное выполнение, yield, IQueryable”

37 · C# в приложении

Тесты сервиса: от модуля до HTTP

~2 h

by the author’s design, after “Хост, DI на практике, конфигурация, логирование”, “Финал: тестируемость и разговор об архитектуре вслух”

final · in the browser, without the assistant

Exam

closed · enrol on the course

The path in words
  • Stage 1 · Что на самом деле происходит, когда вы жмёте F5 — ~2 h
  • Stage 2 · Значимые и ссылочные типы: стек, куча и упаковка — by the author’s design, after “Что на самом деле происходит, когда вы жмёте F5”; ~2 h
  • Stage 3 · Память и время жизни: сборщик мусора, IDisposable, using — by the author’s design, after “Значимые и ссылочные типы: стек, куча и упаковка”; ~2 h
  • Stage 3 · class, struct, record: чем объявлять данные — by the author’s design, after “Значимые и ссылочные типы: стек, куча и упаковка”; ~2 h
  • Stage 3 · Строки: неизменяемость, интернирование, StringBuilder, Span — by the author’s design, after “Значимые и ссылочные типы: стек, куча и упаковка”; ~1.5 h
  • Stage 4 · Равенство, хеш и сравнение: контракт, который легко нарушить — by the author’s design, after “class, struct, record: чем объявлять данные”; ~2 h
  • Stage 4 · null: nullable-типы, ссылочная нулевая аннотация и что с этим делать — by the author’s design, after “class, struct, record: чем объявлять данные”; ~1.5 h
  • Stage 4 · Span, Memory, ref struct и как мерить — by the author’s design, after any one of these: “Значимые и ссылочные типы: стек, куча и упаковка”, “Строки: неизменяемость, интернирование, StringBuilder, Span”; ~2 h
  • Stage 4 · Инкапсуляция и конструирование: объект, который нельзя собрать неправильно — by the author’s design, after “class, struct, record: чем объявлять данные”; ~2 h
  • Stage 5 · Сопоставление с образцом, кортежи, деконструкция — by the author’s design, after any one of these: “class, struct, record: чем объявлять данные”, “null: nullable-типы, ссылочная нулевая аннотация и что с этим делать”; ~2 h
  • Stage 5 · Наследование и полиморфизм: virtual, override, new, sealed — by the author’s design, after “Инкапсуляция и конструирование: объект, который нельзя собрать неправильно”; ~2 h
  • Stage 5 · Делегаты, лямбды, замыкания, события — by the author’s design, after “Инкапсуляция и конструирование: объект, который нельзя собрать неправильно”; ~2 h
  • Stage 5 · Исключения: чем они являются и чем не являются — by the author’s design, after “Инкапсуляция и конструирование: объект, который нельзя собрать неправильно”; ~2 h
  • Stage 6 · Интерфейсы: контракт, явная реализация, DIM — by the author’s design, after “Наследование и полиморфизм: virtual, override, new, sealed”; ~1.5 h
  • Stage 6 · async/await: что это и чего это не — by the author’s design, after “Делегаты, лямбды, замыкания, события”; ~2.5 h
  • Stage 7 · Обобщения: ограничения, реификация, вариантность — by the author’s design, after “Интерфейсы: контракт, явная реализация, DIM”; ~2 h
  • Stage 7 · Данные на границе: JSON, файлы и потоки, даты и время — by the author’s design, after any one of these: “Исключения: чем они являются и чем не являются”, “async/await: что это и чего это не”; ~2 h
  • Stage 7 · Конкурентность: lock, Lock, Interlocked, SemaphoreSlim, Channel, Parallel — by the author’s design, after “async/await: что это и чего это не”; ~2 h
  • Stage 7 · SRP: одна причина для изменения — by the author’s design, after “Интерфейсы: контракт, явная реализация, DIM”; ~2 h
  • Stage 8 · Метаданные: рефлексия, атрибуты, генераторы кода — by the author’s design, after any one of these: “Что на самом деле происходит, когда вы жмёте F5”, “Обобщения: ограничения, реификация, вариантность”; ~2 h
  • Stage 8 · Коллекции: выбор структуры данных и её цена — by the author’s design, after “Обобщения: ограничения, реификация, вариантность”; ~2 h
  • Stage 8 · OCP: открыт для расширения, закрыт для изменения — by the author’s design, after “SRP: одна причина для изменения”; ~2 h
  • Stage 9 · LINQ: отложенное выполнение, yield, IQueryable — by the author’s design, after “Коллекции: выбор структуры данных и её цена”; ~2 h
  • Stage 9 · LSP: подтип обязан быть заменяемым — by the author’s design, after “OCP: открыт для расширения, закрыт для изменения”; ~2 h
  • Stage 10 · ISP: клиента не заставляют зависеть от лишнего — by the author’s design, after “LSP: подтип обязан быть заменяемым”; ~1.5 h
  • Stage 11 · DIP и внедрение зависимостей — by the author’s design, after “ISP: клиента не заставляют зависеть от лишнего”; ~2.5 h
  • Stage 12 · Порождающие паттерны: кто и как создаёт объекты — by the author’s design, after “DIP и внедрение зависимостей”; ~2 h
  • Stage 12 · Структурные паттерны: как собирать объекты в целое — by the author’s design, after “DIP и внедрение зависимостей”; ~2 h
  • Stage 12 · Поведенческие паттерны: кто кого вызывает и когда — by the author’s design, after “DIP и внедрение зависимостей”, “Делегаты, лямбды, замыкания, события”; ~2 h
  • Stage 12 · Хост, DI на практике, конфигурация, логирование — by the author’s design, after “DIP и внедрение зависимостей”; optional; ~2 h
  • Stage 13 · Прикладные паттерны .NET: Repository, Options, CQRS, Result — by the author’s design, after 2 of these: “Порождающие паттерны: кто и как создаёт объекты”, “Структурные паттерны: как собирать объекты в целое”, “Поведенческие паттерны: кто кого вызывает и когда”; ~2 h
  • Stage 13 · Minimal API: конвейер, привязка, валидация, ошибки — by the author’s design, after “Хост, DI на практике, конфигурация, логирование”; optional; ~2 h
  • Stage 13 · HttpClient, устойчивость и фоновые задачи — by the author’s design, after “Хост, DI на практике, конфигурация, логирование”, “async/await: что это и чего это не”; optional; ~2 h
  • Stage 13 · EF Core без иллюзий — by the author’s design, after “Хост, DI на практике, конфигурация, логирование”, “LINQ: отложенное выполнение, yield, IQueryable”; optional; ~2 h
  • Stage 14 · Финал: тестируемость и разговор об архитектуре вслух — by the author’s design, after “Прикладные паттерны .NET: Repository, Options, CQRS, Result”, “async/await: что это и чего это не”; ~2.5 h
  • Stage 14 · Выпуск в Azure: App Service, секреты, managed identity — by the author’s design, after “Minimal API: конвейер, привязка, валидация, ошибки”; optional; ~2 h
  • Stage 15 · Что нового в C# 13 и 14 и как об этом спрашивают — by the author’s design, after “Финал: тестируемость и разговор об архитектуре вслух”; ~2 h
  • Stage 15 · Тесты сервиса: от модуля до HTTP — by the author’s design, after “Хост, DI на практике, конфигурация, логирование”, “Финал: тестируемость и разговор об архитектуре вслух”; optional; ~2 h

Programme · 38 units

1Что на самом деле происходит, когда вы жмёте F5

Описать путь от исходника до машинного кода: Roslyn → IL и метаданные → JIT (tier0 → tier1) → машинный код, и что меняют Debug и Release

~2 h
2Значимые и ссылочные типы: стек, куча и упаковка

Предсказывать поведение кода при присваивании и передаче в метод для значимых и ссылочных типов, включая структуры в коллекциях и кортежи

~2 h
3Память и время жизни: сборщик мусора, IDisposable, using

Объяснить поколенческую сборку и почему её цена определяется выжившими, а не мёртвыми объектами

~2 h
4class, struct, record: чем объявлять данные

Выбирать между class, struct, record class, record struct и readonly record struct по вопросу «значение или сущность», а не по привычке

~2 h
5Равенство, хеш и сравнение: контракт, который легко нарушить

Предсказывать, что сравнивает == и что сравнивает Equals, по статическому и настоящему типу

~2 h
6null: nullable-типы, ссылочная нулевая аннотация и что с этим делать

Различать Nullable<T> и nullable reference types: что делает компилятор, что делает рантайм (особая упаковка) и что не делает никто

~1.5 h
7Сопоставление с образцом, кортежи, деконструкция

Переписывать цепочки if/else с is и приведениями в switch-выражение и объяснять, почему порядок веток — часть смысла

~2 h
8Span, Memory, ref struct и как мерить

Объяснять, что такое Span<T> и ReadOnlySpan<T>, и предсказывать, где срез даёт окно, а где копию

~2 h
9Строки: неизменяемость, интернирование, StringBuilder, Span

Объяснять, что неизменяемость string даёт (безопасная передача, потокобезопасное чтение, надёжный ключ, интернирование) и чего не даёт (кэширования хеша, возможности стереть секрет)

~1.5 h
10Инкапсуляция и конструирование: объект, который нельзя собрать неправильно

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

~2 h
11Наследование и полиморфизм: virtual, override, new, sealed

Точно предсказывать, какая реализация вызовется при virtual/override, new и new virtual, через базовую и производную ссылку

~2 h
12Интерфейсы: контракт, явная реализация, DIM

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

~1.5 h
13Делегаты, лямбды, замыкания, события

Объяснить устройство делегата (Target, Method, список вызова) и предсказать результат многоадресного вызова, в том числе с исключением

~2 h
14Обобщения: ограничения, реификация, вариантность

Объяснить реификацию обобщений: отдельный машинный код для значимых T, общий для ссылочных, реальный тип в рантайме

~2 h
15Метаданные: рефлексия, атрибуты, генераторы кода

Объяснить, что такое метаданные сборки и что делает рефлексия (Type, GetProperties, PropertyInfo.GetValue), и назвать её цену: поиск членов, позднее связывание, упаковка, негарантированный порядок

~2 h
16Коллекции: выбор структуры данных и её цена

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

~2 h
17LINQ: отложенное выполнение, yield, IQueryable

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

~2 h
18Исключения: чем они являются и чем не являются

Решать по контракту метода, что является исключением, а что — ожидаемым результатом

~2 h
19Данные на границе: JSON, файлы и потоки, даты и время

Настроить System.Text.Json для внешнего контракта: один экземпляр JsonSerializerOptions, политика имён, строгость (required, RespectNullableAnnotations, RespectRequiredConstructorParameters из .NET 9), полиморфизм

~2 h
20async/await: что это и чего это не

Объяснить, почему async освобождает поток на время ожидания, а не создаёт новый, и чем масштабируемость отличается от скорости

~2.5 h
21Конкурентность: lock, Lock, Interlocked, SemaphoreSlim, Channel, Parallel

Объяснить гонку read-modify-write и предсказать, что произойдёт с общим полем, которое меняют несколько потоков

~2 h
22SRP: одна причина для изменения

Сформулировать SRP через причину для изменения: один актор, приходящий с требованиями

~2 h
23OCP: открыт для расширения, закрыт для изменения

Объяснить OCP через давление: одно изменение требований — правки в нескольких работающих модулях

~2 h
24LSP: подтип обязан быть заменяемым

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

~2 h
25ISP: клиента не заставляют зависеть от лишнего

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

~1.5 h
26DIP и внедрение зависимостей

Сформулировать обе части DIP и показать, почему вторая (контракт на языке потребителя и у потребителя) важнее

~2.5 h
27Порождающие паттерны: кто и как создаёт объекты

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

~2 h
28Структурные паттерны: как собирать объекты в целое

Различать Adapter, Decorator, Facade и Proxy по намерению и по тому, меняется ли интерфейс

~2 h
29Поведенческие паттерны: кто кого вызывает и когда

Узнавать давление, порождающее Strategy, Template Method, Observer, Command, State и Chain of Responsibility, на коде ENGAGE

~2 h
30Прикладные паттерны .NET: Repository, Options, CQRS, Result

Аргументированно решать, нужен ли свой репозиторий поверх EF Core, и называть, чем обедняет общий IRepository<T>

~2 h
31Что нового в C# 13 и 14 и как об этом спрашивают

Отнести возможность к версии языка: раньше C# 13, C# 13 (.NET 9) или C# 14 (.NET 10) — и не выдавать старое за новое

~2 h
32Финал: тестируемость и разговор об архитектуре вслух

Связывать трудности тестирования с конкретными дефектами проектирования: new внутри метода, статика, DateTime.Now, new HttpClient(), файловая система

~2.5 h
33Хост, DI на практике, конфигурация, логирование

Объяснить, что регистрируют Host.CreateApplicationBuilder и WebApplication.CreateBuilder, и собрать Program.cs как composition root с областями для Scoped-сервисов

~2 h
34Minimal API: конвейер, привязка, валидация, ошибки

Предсказать источник каждого параметра обработчика (маршрут, строка запроса, тело, DI, [AsParameters]) и ответ на ошибку привязки

~2 h
35HttpClient, устойчивость и фоновые задачи

Объяснить, почему new HttpClient() на каждый запрос исчерпывает порты, а вечный статический клиент не видит смены DNS, и выбрать между IHttpClientFactory и долгоживущим клиентом с PooledConnectionLifetime

~2 h
36EF Core без иллюзий

Определять, какая часть LINQ-запроса уйдёт в SQL, а какая выполнится в памяти: Expression против Func, ToList в середине цепочки, непереводимые вызовы методов

~2 h
37Тесты сервиса: от модуля до HTTP

Объяснить, какой класс дефектов ловит каждый уровень тестов сервиса, и выбрать между пирамидой и ромбом по тому, где живут ошибки

~2 h
38Выпуск в Azure: App Service, секреты, managed identity

Опубликовать сервис ENGAGE (dotnet publish) и выбрать режим: framework-dependent, self-contained или ReadyToRun — с ценой каждого

~2 h