← Все гайды

C# / .NET

Сложные вопросы по C# на собеседовании: 10 тем с ответами уровня Middle+

10 сложных тем C# на собеседовании .NET: ref/out/in, using и IAsyncDisposable, делегаты и события, LINQ deferred, value/reference, стек и куча, async, generics, boxing, lock. Как отвечать на Middle/Senior и куда копать дальше.

Не «определение из учебника», а планка собеса

Списки «10 вопросов по C#» часто останавливаются на формулировках для Junior. На Middle+ интервьюер ждёт почему так устроено, где ломается в ASP.NET Core и какой trade-off вы выберете в проде.

Ниже — 10 тем, которые реально всплывают на backend .NET-собесах. Ответы сжатые: ориентир, что говорить вслух за 1–2 минуты.

1. ref, out и in

ref — переменная уже инициализирована; метод может читать и писать; изменения видны вызывающему.

out — инициализация до вызова не обязательна; метод обязан присвоить до выхода (иначе не скомпилируется).

in (readonly ref) — передача по ссылке без права записи; для больших struct снижает копирование.

На собесе плюс: когда out лучше нескольких return-значений через tuple; почему ref struct нельзя в async state machine; зачем Span<T> живёт на стеке.

2. using и dispose

using = try/finally + Dispose() для IDisposable. В C# 8+ — using var на область метода.

Senior-углубление: IAsyncDisposable и await using для HttpClient? Обычно HttpClient — singleton/factory, не dispose на каждый запрос. Для EF DbContext — scope, не «ручной using на весь request» без понимания lifetime.

Вопрос-ловушка: dispose не заменяет GC; финализаторы — крайний случай.

3. Делегаты и события

Делегат — типобезопасный указатель на метод(ы). Action / Func — готовые делегаты. Событие — обёртка: снаружи только += / -=, вызвать может только владелец.

На собесе: multicast, порядок подписчиков не гарантирован как контракт; event vs публичное поле делегата; утечки подписок (-= / weak events); в UI — async void только для handlers.

В ASP.NET чаще IEventBus / MediatR, чем классические event — скажите это осознанно.

4. LINQ: deferred execution

Where / Select строят пайплайн; выполнениеция часто в момент foreach, ToList, Count().

Опасности: повторный перебор → повторный запрос к БД (EF); захват изменяемой переменной в замыкании; AsEnumerable() слишком рано → фильтрация в памяти.

Хороший ответ: «сначала IQueryable до фильтра, материализация осознанно». Связка с EF: N+1, Include, проекции в DTO.

5. Value types vs reference types

Value (struct, числовые, bool) — семантика значения; при присваивании копируется содержимое (с оговорками для ref / in).

Reference (class, массивы, делегаты) — копируется ссылка.

string — reference, но immutable. record class vs record struct — частый уточняющий вопрос 2024–2026.

6. Стек и куча

Стек — кадры вызовов, локальные value (упрощённо); куча — объекты new, управляет GC.

Не говорите «все value только на стеке» — поля class-а лежат в куче внутри объекта. stackalloc / Span — продвинутый уровень: память на стеке, ограничения lifetime.

7. Async/await без воды

Не «не блокирует UI», а: await освобождает поток на I/O; state machine; опасность .Result / .Wait() в ASP.NET; CancellationToken; Task.WhenAll vs параллельный CPU.

Детальный разбор: async/await на собесе .NET.

8. Generics

List<T> без boxing для value types (в отличие от старых non-generic коллекций). Constraints: where T : class, new(). Covariance IEnumerable<out T>, contravariance Action<in T> — с примером «почему List<string> не List<object>».

Senior: generic math (INumber<T>), source generators — только если сами используете.

9. Boxing / unboxing

Value → object / non-generic interface = аллокация на куче. Обратно — unbox с проверкой типа.

Где больно: ArrayList, паттерны с object, частый box в циклах. Современный C#: generics, Span, stackalloc, избегать лишних аллокаций в hot path.

10. lock и синхронизация

lock (obj) = Monitor.Enter/Exit с правильным finally. Блокировать лучше приватный объект, не this и не typeof.

Дальше: ConcurrentDictionary, Interlocked, SemaphoreSlim для async, deadlock при вложенных lock. В ASP.NET — не lock на долгий I/O; для кэша — правильная абстракция, не «глобальный static lock на всё».

Как готовить эти темы за неделю

День 1–2: value/reference, boxing, stack/heap — своими словами + один пример из вашего кода.

День 3–4: LINQ deferred + один баг N+1 из опыта (или учебный).

День 5: async — без .Result, с CancellationToken.

День 6: lock / concurrent + когда lock не нужен.

День 7: mock — прогнать теорию вслух, не «прочитал глазами».

Шпаргалка по широте тем: что спрашивают на .NET-собесах. Live coding рядом: отдельный гайд.

Связанные материалы

---

*Прогнать сложные вопросы C# на mock — с фидбеком и записью. excalib.ru.*