Как устроить высокопроизводительную сериализацию JSON без лишних аллокаций?
Реюзайте один JsonSerializerOptions (кешируйте статически), используйте System.Text.Json с Utf8JsonWriter/IAsyncEnumerable<T> для стриминга, избегайте промежуточных строк, включайте source-generators (JsonSerializerContext) вместо рефлексии, буферизуйте через ArrayPool<byte> и пишите напрямую в PipeWriter/BodyWriter.
Библиотека собеса по С#
Библиотека собеса по С#
Разница между LINQ lazy loading и eager loading
В случае lazy loading зависимые таблицы (дочерние объекты) не загружаются автоматически с родительскими, а загрузятся в тот момент, когда они понадобятся. В LINQ по умолчанию используется lazy loading.
В случае eager loading зависимые объекты загружаются автоматически с родительской таблицей. Для того, чтобы использовать eager loading, нужно применить метод Include().
🐸 Библиотека собеса по С#
В случае lazy loading зависимые таблицы (дочерние объекты) не загружаются автоматически с родительскими, а загрузятся в тот момент, когда они понадобятся. В LINQ по умолчанию используется lazy loading.
В случае eager loading зависимые объекты загружаются автоматически с родительской таблицей. Для того, чтобы использовать eager loading, нужно применить метод Include().
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Покупать новый курс каждый раз, когда меняется рабочая задача, — довольно странная механика. Нашли альтернативу 👇
🥱1
Forwarded from Proglib.academy | IT-курсы
Сегодня хочется разобраться в AI-агентах. Через пару недель появляется задача, где нужны алгоритмы. Потом понимаешь, что неплохо бы освежить Python или математику для Data Science.
В подписку Proglib Academy входят все основные направления — AI, ML, Python, алгоритмы, математика для DS и другие курсы, а ещё закрытый видеохаб с вебинарами практиков.
Начать можно с пробного месяца. Если решите остаться, его стоимость зачтётся при оформлении подписки
Please open Telegram to view this post
VIEW IN TELEGRAM
Долгоживущий .NET-сервис постепенно “распухает” по памяти без явных LOH-пиков. В дампе видно множество делегатов/лямбд, Timer и CancellationTokenRegistration, висящих в Gen2. Как диагностировать и устранить утечки из-за событий/таймеров/регистраций?
Проанализировать пути до корней (dotMemory/PerfView/dotnet-dump gcroot) — проверить коллекции подписчиков и списки делегатов у источников событий. Убедиться, что:
✍🏻 все подписки снимаются в Dispose/IAsyncDisposable;
✍🏻 CancellationToken.Register хранит IDisposable и корректно Dispose();
✍🏻 Timer/PeriodicTimer/System.Threading.Channels закрываются/завершаются;
✍🏻 не удерживаются замыканиями большие объекты/this.
При необходимости — слабые события/WeakReference, паттерн “own the lifetime”, и тест “утечек” в CI с сравнением heap-снимков.
Библиотека собеса по С#
✍🏻 все подписки снимаются в Dispose/IAsyncDisposable;
✍🏻 CancellationToken.Register хранит IDisposable и корректно Dispose();
✍🏻 Timer/PeriodicTimer/System.Threading.Channels закрываются/завершаются;
✍🏻 не удерживаются замыканиями большие объекты/this.
При необходимости — слабые события/WeakReference, паттерн “own the lifetime”, и тест “утечек” в CI с сравнением heap-снимков.
Библиотека собеса по С#
❤1🥱1
Разберём на вебинаре, как тратить меньше на AI-агентов — без потери качества кода.
— когда дорогая модель действительно нужна, а когда хватит дешёвой;
— сколько стоит один прогон и куда уходят токены;
— какие задачи можно отдавать субагентам;
— как настроить маршрутизацию моделей;
— что проверять в AI-коде перед merge.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Когда выбирать struct/record struct вместо class?
Для маленьких, неизменяемых и часто копируемых значений (≤ ~16–32 байт), где важна локальность и отсутствие аллокаций. Нужны структурное равенство/with — берите record struct. Если объект крупный/мутабельный/долго живёт — используйте class.
Библиотека собеса по С#
Библиотека собеса по С#
❤3
Forwarded from Библиотека программиста
Разбираете урок, слушаете интервью фоном или начинаете на телефоне, а продолжаете на большом экране?
Хотим узнать, что делает просмотр удобным для вас. Вспомните последнее видео — ролик, урок, фильм или серию сериала — и расскажите о своём опыте. Если детали не запомнились, можно так и ответить.
В результатах сможете сравнить свои привычки с ответами других участников. А разработчики и инженеры видеоплатформы расскажут, что происходит по ту сторону экрана, пока вы смотрите видео.
Please open Telegram to view this post
VIEW IN TELEGRAM
Можно ли после Cancel вернуть CancellationTokenSource в рабочее состояние через TryReset?
Нет. Если отмена уже запрошена, TryReset возвращает false. Это не кнопка «отменить отмену». Проверка на .NET 8 подтвердила false после Cancel, а для свежего источника вернула true.
Метод предназначен для единственного владельца источника: предыдущая операция завершена, никто больше не должен запросить её отмену, оставшиеся регистрации больше не нужны. Успешный reset удаляет регистрации.
Одновременный вызов Cancel не является потокобезопасным сценарием. Также нельзя считать старый токен отдельным поколением: он всё ещё связан с тем же источником. Для независимых операций проще создавать отдельные источники отмены.
Контракт TryReset
Библиотека собеса по C#
Метод предназначен для единственного владельца источника: предыдущая операция завершена, никто больше не должен запросить её отмену, оставшиеся регистрации больше не нужны. Успешный reset удаляет регистрации.
Одновременный вызов Cancel не является потокобезопасным сценарием. Также нельзя считать старый токен отдельным поколением: он всё ещё связан с тем же источником. Для независимых операций проще создавать отдельные источники отмены.
Контракт TryReset
Библиотека собеса по C#
❤1
WaitAsync завершился по тайм-ауту. Исходная Task тоже остановилась?
Нет, сам WaitAsync ограничивает ожидание. В проверке на .NET 8 исходная задача возвращала 42 после задержки. Ожидание с коротким тайм-аутом выбросило TimeoutException, но последующий await исходной задачи всё равно получил 42.
Чтобы остановить работу, она должна поддерживать отмену: токен передают в саму операцию, а операция проверяет его или использует API, который это делает. Токен, переданный только в WaitAsync, не добавляет такой поддержки исходному коду.
Поэтому после тайм-аута надо решить, кто отвечает за продолжающуюся операцию, её ресурсы и возможное позднее исключение. «Перестали ждать» и «работа завершилась» — разные состояния.
Контракт Task.WaitAsync
Библиотека собеса по C#
Чтобы остановить работу, она должна поддерживать отмену: токен передают в саму операцию, а операция проверяет его или использует API, который это делает. Токен, переданный только в WaitAsync, не добавляет такой поддержки исходному коду.
Поэтому после тайм-аута надо решить, кто отвечает за продолжающуюся операцию, её ресурсы и возможное позднее исключение. «Перестали ждать» и «работа завершилась» — разные состояния.
Контракт Task.WaitAsync
Библиотека собеса по C#
Чем init отличается от set и делает ли он объект неизменяемым?
Ответ: Нет, init сам по себе не делает весь объект неизменяемым.
Свойству с set можно присваивать значение после создания объекта, если позволяет доступ. init ограничивает присваивание этапом инициализации: например, значение можно задать в инициализаторе объекта, а обычное присваивание после этого компилятор запретит.
Но если свойство хранит List<string>, вызов Add по-прежнему допустим. init запрещает заменить ссылку на список после инициализации, а не менять содержимое списка.
На собеседовании стоит разделять две вещи: возможность присвоить свойству новое значение и возможность изменить объект, на который оно ссылается. init появился в C# 9.
Подробнее в документации Microsoft Learn
🐸 Библиотека собеса по C#
Свойству с set можно присваивать значение после создания объекта, если позволяет доступ. init ограничивает присваивание этапом инициализации: например, значение можно задать в инициализаторе объекта, а обычное присваивание после этого компилятор запретит.
Но если свойство хранит List<string>, вызов Add по-прежнему допустим. init запрещает заменить ссылку на список после инициализации, а не менять содержимое списка.
На собеседовании стоит разделять две вещи: возможность присвоить свойству новое значение и возможность изменить объект, на который оно ссылается. init появился в C# 9.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
The init keyword - init only properties - C# reference
The `init` keyword is used to declare a `set` accessor that can only be called during an object's initialization: either by a constructor or as part of an object initializer.
До 31 октября в Proglib Academy можно выбрать два курса и заплатить только за один.
Например, можно совместить:
💥 ИИ для разработчиков — применение нейросетей в повседневной разработке: работа с кодом, тестирование и ревью.💥 Разработка ИИ-агентов — архитектура агентов и создание собственных AI-решений.
Вместе курсы стоят 108 000 ₽, но по акции оба обойдутся в 59 000 ₽. Экономия — 49 000 ₽
Интересуют Python и ИИ или алгоритмы и архитектура? Можно выбрать любые два курса из каталога.
Please open Telegram to view this post
VIEW IN TELEGRAM
Гарантирует ли required, что свойство не будет равно null?
Ответ: Нет. required требует инициализации члена при создании объекта, но не проверяет его значение во время выполнения.
Для свойства required string Name { get; init; } выражение new User() вызовет ошибку компиляции. А new User { Name = null } удовлетворит требованию required. При включённом анализе nullable компилятор выдаст предупреждение о присваивании null; настройки проекта могут превращать такие предупреждения в ошибки.
Атрибут SetsRequiredMembers тоже не доказывает, что конструктор всё заполнил: компилятор доверяет этому обещанию автора.
Поэтому required не заменяет проверку аргументов и правил предметной области. Модификатор доступен с C# 11.
Подробнее в документации Microsoft Learn
🐸 Библиотека собеса по C#
Для свойства required string Name { get; init; } выражение new User() вызовет ошибку компиляции. А new User { Name = null } удовлетворит требованию required. При включённом анализе nullable компилятор выдаст предупреждение о присваивании null; настройки проекта могут превращать такие предупреждения в ошибки.
Атрибут SetsRequiredMembers тоже не доказывает, что конструктор всё заполнил: компилятор доверяет этому обещанию автора.
Поэтому required не заменяет проверку аргументов и правил предметной области. Модификатор доступен с C# 11.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
required modifier - C# reference
👍1
Защищает ли оператор ! от NullReferenceException?
Ответ: Нет. Постфиксный ! подавляет предупреждения nullable-анализа для выражения, но ничего не проверяет во время выполнения.
Если переменная value содержит null, обращение value!.Length всё равно завершится NullReferenceException. Оператор не создаёт объект, не подставляет значение и не добавляет проверку.
Использовать ! стоит, когда у разработчика есть основание считать значение ненулевым, а компилятор этого не видит. Если значение действительно может отсутствовать, нужна обработка этого случая: проверка null, условный доступ ?. или подходящее исключение.
Не путайте постфиксный value! с логическим отрицанием !flag. Подавление nullable-предупреждений доступно с C# 8.
Подробнее в документации Microsoft Learn
🐸 Библиотека собеса по C#
Если переменная value содержит null, обращение value!.Length всё равно завершится NullReferenceException. Оператор не создаёт объект, не подставляет значение и не добавляет проверку.
Использовать ! стоит, когда у разработчика есть основание считать значение ненулевым, а компилятор этого не видит. Если значение действительно может отсутствовать, нужна обработка этого случая: проверка null, условный доступ ?. или подходящее исключение.
Не путайте постфиксный value! с логическим отрицанием !flag. Подавление nullable-предупреждений доступно с C# 8.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
! (null-forgiving) operator - C# reference
Learn about the C# null-forgiving, or null-suppression, operator that is used to declare that an expression of a reference type isn't null.
🥱2
Распространяется ли checked на арифметику внутри вызванного метода?
Ответ: Нет. Контекст checked действует на операции, записанные внутри него, и не переносится через вызов в тело другого метода.
Допустим, метод AddOne(int x) возвращает x + 1. Если обернуть вызов AddOne(int.MaxValue) в checked, это само по себе не заставит сложение внутри AddOne выбросить OverflowException.
Поведение сложения определяется контекстом в самом методе и настройками проверки переполнения при его компиляции. Чтобы явно проверять эту операцию, нужно написать checked(x + 1) в AddOne.
Поэтому без знания настроек компиляции нельзя уверенно обещать конкретный результат исходного примера. Важный принцип: checked не включает проверку во всём стеке вызовов.
Подробнее в документации Microsoft Learn
🐸 Библиотека собеса по C#
Допустим, метод AddOne(int x) возвращает x + 1. Если обернуть вызов AddOne(int.MaxValue) в checked, это само по себе не заставит сложение внутри AddOne выбросить OverflowException.
Поведение сложения определяется контекстом в самом методе и настройками проверки переполнения при его компиляции. Чтобы явно проверять эту операцию, нужно написать checked(x + 1) в AddOne.
Поэтому без знания настроек компиляции нельзя уверенно обещать конкретный результат исходного примера. Важный принцип: checked не включает проверку во всём стеке вызовов.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
The checked and unchecked statements - overflow-checking - C# reference
Control the overflow-checking context. In a checked context, overflow causes an exception to be thrown. In an unchecked context, the result is truncated.
🤔1
В Proglib Academy действует акция: покупаешь один курс, а второй получаешь в подарок.
Например, можно совместить два направления по работе с ИИ:
💥 ИИ для разработчиков — применение нейросетей в повседневной разработке: работа с кодом, тестирование и ревью.💥 Разработка ИИ-агентов — архитектура агентов и создание собственных AI-решений.
А если тебе интереснее Python, алгоритмы, backend или DevOps — выбирай другую пару курсов из каталога.
Акция действует до 31 октября включительно
Please open Telegram to view this post
VIEW IN TELEGRAM
Чем catch с when отличается от проверки if внутри catch?
Ответ: Фильтр when определяет, подходит ли обработчик, ещё до раскрутки стека. Условие if выполняется уже после входа в catch.
В конструкции catch (Exception ex) when (CanHandle(ex)) обработчик будет выбран только при истинном результате фильтра. Если фильтр вернул false, поиск подходящего catch продолжается. В том числе может сработать следующий catch у того же try.
Если же проверять условие внутри catch, исключение уже перехвачено. Чтобы передать его дальше, придётся явно выполнить throw; — к следующим catch того же try выполнение уже не перейдёт.
При этом throw; сохраняет исходный стек исключения. Его не стоит заменять на throw ex;, который меняет информацию о стеке.
Подробнее в документации Microsoft Learn
🐸 Библиотека собеса по C#
В конструкции catch (Exception ex) when (CanHandle(ex)) обработчик будет выбран только при истинном результате фильтра. Если фильтр вернул false, поиск подходящего catch продолжается. В том числе может сработать следующий catch у того же try.
Если же проверять условие внутри catch, исключение уже перехвачено. Чтобы передать его дальше, придётся явно выполнить throw; — к следующим catch того же try выполнение уже не перейдёт.
При этом throw; сохраняет исходный стек исключения. Его не стоит заменять на throw ex;, который меняет информацию о стеке.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
Exception-handling statements - throw and try, catch, finally - C# reference
Use the C# throw statement to signal an occurrence of an exception. Use the C# try statements to catch and process exceptions occurred in a block of code.
Будет ли повторно вызван статический конструктор после исключения?
Ответ: Нет. Если статический конструктор завершился необработанным исключением, среда выполнения не запускает его заново для того же загруженного типа.
Тип остаётся неинициализированным. Обращение, требующее его инициализации, обычно приводит к TypeInitializationException; исходную причину можно посмотреть в InnerException. Повторный вызов такого обращения не становится повторной попыткой выполнить конструктор.
Поэтому временно недоступный сервер или файл — плохая зависимость для статического конструктора. Даже если ресурс появится позже, автоматического восстановления типа не произойдёт.
Если операции нужны повторные попытки, их следует организовать отдельно от статической инициализации.
Подробнее в документации Microsoft Learn
🐸 Библиотека собеса по C#
Тип остаётся неинициализированным. Обращение, требующее его инициализации, обычно приводит к TypeInitializationException; исходную причину можно посмотреть в InnerException. Повторный вызов такого обращения не становится повторной попыткой выполнить конструктор.
Поэтому временно недоступный сервер или файл — плохая зависимость для статического конструктора. Даже если ресурс появится позже, автоматического восстановления типа не произойдёт.
Если операции нужны повторные попытки, их следует организовать отдельно от статической инициализации.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
Static Constructors - C#
A static constructor in C# initializes static data or performs an action done only once. It runs before the first instance is created or static members are referenced.
Где искать все исключения, если несколько задач в Task.WhenAll завершились с ошибкой?
Ответ: В свойстве Exception задачи, которую вернул Task.WhenAll. Оно содержит AggregateException с ошибками завершившихся задач. При await обычно выбрасывается одно из этих исключений, поэтому одного пойманного исключения недостаточно, чтобы узнать обо всех сбоях. Сохраните общую задачу в переменную, дождитесь её и при ошибке проверьте Exception.InnerExceptions. Для вложенных агрегатов можно использовать Flatten(). WhenAll дожидается всех переданных задач, а не завершается сразу после первой ошибки.
Документация: Task.WhenAll
Основа вопроса: Список собеседований Alibaba Travels, раздел Task.WhenAll.
➡️ Навигация: База знаний • Задачи • Собеседования • Вакансии
🐸 Библиотека программиста
Основа вопроса: Список собеседований Alibaba Travels, раздел Task.WhenAll.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
Task.WhenAll Method (System.Threading.Tasks)
Creates a task that will complete when all of the supplied tasks have completed.
Чем ExecutionContext отличается от SynchronizationContext?
Ответ: ExecutionContext переносит логическое окружение выполнения, например значения AsyncLocal. SynchronizationContext определяет, как и куда отправить продолжение: например, в очередь потока интерфейса. Это разные механизмы. ConfigureAwait(false) отключает попытку вернуться в захваченный контекст синхронизации, но сам по себе не запрещает перенос ExecutionContext. Поэтому значения AsyncLocal обычно сохраняются и после такого await.
Документация: ExecutionContext и SynchronizationContext
Основа вопроса: Список собеседований Alibaba Travels.
➡️ Навигация: База знаний • Задачи • Собеседования • Вакансии
🐸 Библиотека программиста
Основа вопроса: Список собеседований Alibaba Travels.
Please open Telegram to view this post
VIEW IN TELEGRAM
Microsoft News
ExecutionContext vs SynchronizationContext
I’ve been asked a few times recently various questions about ExecutionContext and SynchronizationContext, for example what the differences are between them, what it means to “flow” them, and how they relate to the new async/await keywords in C# and Visual…