В третьем предварительном выпуске .NET 10 Preview 3, Microsoft сосредоточила внимание на улучшении производительности, удобстве для разработчиков и современных облачных паттернах.
Хотя этот выпуск не содержит значимых новых функций, он предлагает значительные усовершенствования в различных областях.
🔧 Основные нововведения
🐳 Нативная публикация контейнеров для консольных приложений
Теперь консольные приложения могут создавать контейнерные образы с помощью команды:
Это стало возможным без необходимости устанавливать свойство <EnableSdkContainerSupport> в значение true в файле проекта. Если требуется отключить эту поддержку, можно установить это свойство в false.
📦 Управление форматом контейнерных образов
Разработчики получили возможность явно указывать формат контейнерного образа (.Docker или .OCI) с помощью нового свойства <ContainerImageFormat> в SDK. По умолчанию SDK выбирает формат на основе архитектуры контейнера и базового образа, но теперь это поведение можно переопределить, что особенно полезно для команд, стандартизирующихся на формате OCI.
🌐 Обновления для облачных и веб-приложений
ASP.NET Core: Добавлена поддержка OpenAPI 3.1, что обеспечивает лучшую интеграцию с современными API-шлюзами и инструментами проектирования. Также теперь можно обслуживать документы OpenAPI в формате YAML, что широко используется в инфраструктуре как код и DevOps-процессах.
Blazor Web Apps: Введён новый компонент ReconnectModal для более плавной обработки отключений клиента. Улучшения также коснулись компонента QuickGrid, включая условное стилизование строк и управление пользовательским интерфейсом. Навигация стала более предсказуемой, избегая ненужной прокрутки страниц и лучше обрабатывая строки запроса. Кроме того, скрипт фреймворка Blazor теперь обслуживается как статический веб-ресурс с отпечатком, улучшая кэширование и производительность, особенно в средах с CDN или на периферии сети.
⚙️ Дополнительные улучшения
Оптимизация SDK: Автоматическое удаление неиспользуемых ссылок на пакеты, предоставляемые фреймворком, что снижает использование диска и улучшает производительность сборки.
- Улучшения CLI:
Введены новые алиасы команд, такие как dotnet package add, для повышения ясности и согласованности командной строки.
Теперь можно генерировать скрипты автодополнения оболочки с помощью команды dotnet completions generate <SHELL> для bash, zsh, powershell и других.
В интерактивных терминалах команды CLI теперь по умолчанию работают в интерактивном режиме, упрощая взаимодействие с пользователем.
- Улучшения JIT-компилятора:
Возможность деинлайнить и инлайнить методы интерфейса на массивах, улучшая производительность в коде с интенсивным использованием коллекций.
Оптимизация перечисления массивов, позволяющая лучшую инлайнизацию JIT и размещение в стеке.
Поддержка инлайнинга методов, которые становятся деинлайненными после предыдущих шагов инлайнинга.
Разрешение размещения в стеке для небольших массивов фиксированного размера, состоящих из типов значений без указателей GC, снижая нагрузку на кучу.
- Новые API и улучшения:
Поддержка поиска сертификатов по отпечатку с использованием алгоритмов, отличных от SHA-1, таких как SHA-256.
Улучшения в кодировании PEM: API PEM теперь поддерживают чтение ASCII/UTF-8 текста напрямую, упрощая кроссплатформенную работу с ключами и сертификатами.
Поддержка DateOnly в ISOWeek: новые перегрузки для работы со значениями DateOnly в логике, основанной на неделях.
Нормализация строк для Span<char> и ReadOnlySpan<char>: новые API позволяют выполнять нормализацию Unicode напрямую на этих типах, снижая количество выделений памяти.
Для получения более подробной информации сюда
Хотя этот выпуск не содержит значимых новых функций, он предлагает значительные усовершенствования в различных областях.
🔧 Основные нововведения
🐳 Нативная публикация контейнеров для консольных приложений
Теперь консольные приложения могут создавать контейнерные образы с помощью команды:
dotnet publish /t:PublishContainer
Это стало возможным без необходимости устанавливать свойство <EnableSdkContainerSupport> в значение true в файле проекта. Если требуется отключить эту поддержку, можно установить это свойство в false.
📦 Управление форматом контейнерных образов
Разработчики получили возможность явно указывать формат контейнерного образа (.Docker или .OCI) с помощью нового свойства <ContainerImageFormat> в SDK. По умолчанию SDK выбирает формат на основе архитектуры контейнера и базового образа, но теперь это поведение можно переопределить, что особенно полезно для команд, стандартизирующихся на формате OCI.
🌐 Обновления для облачных и веб-приложений
ASP.NET Core: Добавлена поддержка OpenAPI 3.1, что обеспечивает лучшую интеграцию с современными API-шлюзами и инструментами проектирования. Также теперь можно обслуживать документы OpenAPI в формате YAML, что широко используется в инфраструктуре как код и DevOps-процессах.
Blazor Web Apps: Введён новый компонент ReconnectModal для более плавной обработки отключений клиента. Улучшения также коснулись компонента QuickGrid, включая условное стилизование строк и управление пользовательским интерфейсом. Навигация стала более предсказуемой, избегая ненужной прокрутки страниц и лучше обрабатывая строки запроса. Кроме того, скрипт фреймворка Blazor теперь обслуживается как статический веб-ресурс с отпечатком, улучшая кэширование и производительность, особенно в средах с CDN или на периферии сети.
⚙️ Дополнительные улучшения
Оптимизация SDK: Автоматическое удаление неиспользуемых ссылок на пакеты, предоставляемые фреймворком, что снижает использование диска и улучшает производительность сборки.
- Улучшения CLI:
Введены новые алиасы команд, такие как dotnet package add, для повышения ясности и согласованности командной строки.
Теперь можно генерировать скрипты автодополнения оболочки с помощью команды dotnet completions generate <SHELL> для bash, zsh, powershell и других.
В интерактивных терминалах команды CLI теперь по умолчанию работают в интерактивном режиме, упрощая взаимодействие с пользователем.
- Улучшения JIT-компилятора:
Возможность деинлайнить и инлайнить методы интерфейса на массивах, улучшая производительность в коде с интенсивным использованием коллекций.
Оптимизация перечисления массивов, позволяющая лучшую инлайнизацию JIT и размещение в стеке.
Поддержка инлайнинга методов, которые становятся деинлайненными после предыдущих шагов инлайнинга.
Разрешение размещения в стеке для небольших массивов фиксированного размера, состоящих из типов значений без указателей GC, снижая нагрузку на кучу.
- Новые API и улучшения:
Поддержка поиска сертификатов по отпечатку с использованием алгоритмов, отличных от SHA-1, таких как SHA-256.
Улучшения в кодировании PEM: API PEM теперь поддерживают чтение ASCII/UTF-8 текста напрямую, упрощая кроссплатформенную работу с ключами и сертификатами.
Поддержка DateOnly в ISOWeek: новые перегрузки для работы со значениями DateOnly в логике, основанной на неделях.
Нормализация строк для Span<char> и ReadOnlySpan<char>: новые API позволяют выполнять нормализацию Unicode напрямую на этих типах, снижая количество выделений памяти.
Для получения более подробной информации сюда
Вы используете локальные переменные в LINQ и используете let? 👇
Ключевое слово let позволяет вводить временную переменную прямо внутри запроса LINQ — как локальную переменную в цикле.
Разбивайте сложные вычисления на части
Делайте запрос модульнее и чище
Меньше проходов по данным → выше производительность
👉 Простой пример:
csharp
Ключевое слово let позволяет вводить временную переменную прямо внутри запроса LINQ — как локальную переменную в цикле.
Разбивайте сложные вычисления на части
Делайте запрос модульнее и чище
Меньше проходов по данным → выше производительность
👉 Простой пример:
csharp
from order in orders
let total = order.Items.Sum(i => i.Price * i.Quantity)
where total > 1000
let categories = order.Items.Select(i => i.Category).Distinct()
select new
{
OrderId = order.Id,
Total = total,
Categories = categories
};
let total
= … — вычисляем сумму заказа только один разwhere total >
1000 — фильтруем по готовому значениюlet categories =
… — собираем уникальные категории⚡️Легкий способ получать свежие обновления и следить за трендами в разработке на вашем языке. Находите свой стек и подписывайтесь:
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Собеседования DS: t.me/machinelearning_interview
Нерйросети t.me/ai_machinelearning_big_data
C++ t.me/cpluspluc
Docker: t.me/DevopsDocker
Хакинг: t.me/linuxkalii
Devops: t.me/DevOPSitsec
Data Science: t.me/data_analysis_ml
Javascript: t.me/javascriptv
C#: t.me/csharp_ci
Java: t.me/javatg
Базы данных: t.me/sqlhub
Python собеседования: t.me/python_job_interview
Мобильная разработка: t.me/mobdevelop
Golang: t.me/Golang_google
React: t.me/react_tg
Rust: t.me/rust_code
ИИ: t.me/vistehno
PHP: t.me/phpshka
Android: t.me/android_its
Frontend: t.me/front
Big Data: t.me/bigdatai
МАТЕМАТИКА: t.me/data_math
Kubernets: t.me/kubernetc
Разработка игр: https://t.me/gamedev
Haskell: t.me/haskell_tg
Физика: t.me/fizmat
💼 Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: https://t.me/addlist/2Ls-snqEeytkMDgy
Папка FRONTEND: https://t.me/addlist/mzMMG3RPZhY2M2Iy
😆ИТ-Мемы: t.me/memes_prog
🇬🇧Английский: t.me/english_forprogrammers
🧠ИИ: t.me/vistehno
🎓954ГБ ОПЕНСОРС КУРСОВ: @courses
📕Ит-книги бесплатно: https://t.me/addlist/BkskQciUW_FhNjEy
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Собеседования DS: t.me/machinelearning_interview
Нерйросети t.me/ai_machinelearning_big_data
C++ t.me/cpluspluc
Docker: t.me/DevopsDocker
Хакинг: t.me/linuxkalii
Devops: t.me/DevOPSitsec
Data Science: t.me/data_analysis_ml
Javascript: t.me/javascriptv
C#: t.me/csharp_ci
Java: t.me/javatg
Базы данных: t.me/sqlhub
Python собеседования: t.me/python_job_interview
Мобильная разработка: t.me/mobdevelop
Golang: t.me/Golang_google
React: t.me/react_tg
Rust: t.me/rust_code
ИИ: t.me/vistehno
PHP: t.me/phpshka
Android: t.me/android_its
Frontend: t.me/front
Big Data: t.me/bigdatai
МАТЕМАТИКА: t.me/data_math
Kubernets: t.me/kubernetc
Разработка игр: https://t.me/gamedev
Haskell: t.me/haskell_tg
Физика: t.me/fizmat
💼 Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: https://t.me/addlist/2Ls-snqEeytkMDgy
Папка FRONTEND: https://t.me/addlist/mzMMG3RPZhY2M2Iy
😆ИТ-Мемы: t.me/memes_prog
🇬🇧Английский: t.me/english_forprogrammers
🧠ИИ: t.me/vistehno
🎓954ГБ ОПЕНСОРС КУРСОВ: @courses
📕Ит-книги бесплатно: https://t.me/addlist/BkskQciUW_FhNjEy
📌 Задача: "Высоконагружённый кэш с автоматической очисткой и конкурентным доступом"
❗️Условие:
Реализуйте класс
- Позволять безопасно добавлять и получать элементы из кэша в многопоточной среде (`Get`, `Set`).
- Автоматически удалять элементы через N секунд после их добавления (TTL).
- Поддерживать высокую производительность при массовом доступе (тысячи операций в секунду).
- Минимизировать блокировки (`lock`) или использовать неблокирующие структуры.
- Корректно работать с истекшими элементами:
- Не возвращать их через
- Не копить мусор в памяти.
---
▪️ Ограничения:
- Можно использовать стандартные коллекции .NET (`ConcurrentDictionary`,
- Нельзя использовать внешние библиотеки типа
- Нужно поддерживать работу под большой нагрузкой (много ключей и операций параллельно).
---
▪️ Подсказки:
- Для конкурентного доступа подойдёт
- Для очистки устаревших данных:
- Можно использовать фоновую задачу (`Task`) с таймером, которая периодически чистит старые записи.
- Обратите внимание на гонки состояний: между проверкой срока жизни элемента и его удалением.
---
▪️ Что оценивается:
- Умение проектировать потокобезопасные структуры данных.
- Продуманность балансировки между скоростью операций и частотой очистки.
- Правильная работа со временем жизни (`TTL`).
- Чистота и лаконичность кода.
---
▪️ Разбор возможного решения:
▪️ Основная идея:
- В кэше храним не просто значение, а пару (значение + время истечения).
- При
- Проверяем, истёк ли элемент.
- Если истёк — удаляем его и возвращаем
- При
- Сохраняем значение с текущим временем + TTL.
- Отдельная фоновая задача (`Task`) регулярно сканирует кэш и удаляет устаревшие элементы.
▪️ Мини-пример структуры:
📌 Важные моменты:
- Кэш конкурентный (`ConcurrentDictionary`) — доступ без явных блокировок.
- Периодическая чистка не мешает основным операциям.
- Удаление истёкших элементов происходит "мягко" (через проверку срока жизни).
- Фоновая задача корректно завершается через
❗️Условие:
Реализуйте класс
SmartCache<TKey, TValue>
в .NET, который должен:- Позволять безопасно добавлять и получать элементы из кэша в многопоточной среде (`Get`, `Set`).
- Автоматически удалять элементы через N секунд после их добавления (TTL).
- Поддерживать высокую производительность при массовом доступе (тысячи операций в секунду).
- Минимизировать блокировки (`lock`) или использовать неблокирующие структуры.
- Корректно работать с истекшими элементами:
- Не возвращать их через
Get
.- Не копить мусор в памяти.
---
▪️ Ограничения:
- Можно использовать стандартные коллекции .NET (`ConcurrentDictionary`,
Timer
, Task
, CancellationToken
и т.д.).- Нельзя использовать внешние библиотеки типа
MemoryCache
, Redis
, LazyCache
и др.- Нужно поддерживать работу под большой нагрузкой (много ключей и операций параллельно).
---
▪️ Подсказки:
- Для конкурентного доступа подойдёт
ConcurrentDictionary<TKey, ValueWithExpiry>
.- Для очистки устаревших данных:
- Можно использовать фоновую задачу (`Task`) с таймером, которая периодически чистит старые записи.
- Обратите внимание на гонки состояний: между проверкой срока жизни элемента и его удалением.
---
▪️ Что оценивается:
- Умение проектировать потокобезопасные структуры данных.
- Продуманность балансировки между скоростью операций и частотой очистки.
- Правильная работа со временем жизни (`TTL`).
- Чистота и лаконичность кода.
---
▪️ Разбор возможного решения:
▪️ Основная идея:
- В кэше храним не просто значение, а пару (значение + время истечения).
- При
Get(key)
:- Проверяем, истёк ли элемент.
- Если истёк — удаляем его и возвращаем
null
или default
.- При
Set(key, value)
:- Сохраняем значение с текущим временем + TTL.
- Отдельная фоновая задача (`Task`) регулярно сканирует кэш и удаляет устаревшие элементы.
▪️ Мини-пример структуры:
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
public class SmartCache<TKey, TValue>
{
private readonly ConcurrentDictionary<TKey, (TValue Value, DateTime Expiry)> _cache = new();
private readonly TimeSpan _ttl;
private readonly CancellationTokenSource _cts = new();
public SmartCache(TimeSpan ttl)
{
_ttl = ttl;
StartCleanupTask();
}
public void Set(TKey key, TValue value)
{
_cache[key] = (value, DateTime.UtcNow.Add(_ttl));
}
public TValue Get(TKey key)
{
if (_cache.TryGetValue(key, out var entry))
{
if (entry.Expiry > DateTime.UtcNow)
{
return entry.Value;
}
else
{
_cache.TryRemove(key, out _);
}
}
return default;
}
private void StartCleanupTask()
{
Task.Run(async () =>
{
while (!_cts.Token.IsCancellationRequested)
{
foreach (var key in _cache.Keys)
{
if (_cache.TryGetValue(key, out var entry) && entry.Expiry <= DateTime.UtcNow)
{
_cache.TryRemove(key, out _);
}
}
await Task.Delay(TimeSpan.FromSeconds(30), _cts.Token); // периодическая очистка
}
});
}
public void Dispose()
{
_cts.Cancel();
}
}
📌 Важные моменты:
- Кэш конкурентный (`ConcurrentDictionary`) — доступ без явных блокировок.
- Периодическая чистка не мешает основным операциям.
- Удаление истёкших элементов происходит "мягко" (через проверку срока жизни).
- Фоновая задача корректно завершается через
CancellationToken
.Forwarded from C# (C Sharp) programming
🚀 Silk.NET 3.0: грядущая революция в .NET-графике
Сообщество Silk.NET анонсировало работу над третьей версией своего фреймворка — амбициозным переосмыслением того, как должны работать низкоуровневые .NET-биндинги для графики и мультимедиа.
Особенность проекта всегда заключалась в кроссплатформенности и минимальных накладных расходах при работе с GPU. В 3.0 разработчики обещают переработанную систему биндингов и улучшенную интеграцию с современными .NET-стэками.
🤖 GitHub
@csharp_ci
Сообщество Silk.NET анонсировало работу над третьей версией своего фреймворка — амбициозным переосмыслением того, как должны работать низкоуровневые .NET-биндинги для графики и мультимедиа.
Особенность проекта всегда заключалась в кроссплатформенности и минимальных накладных расходах при работе с GPU. В 3.0 разработчики обещают переработанную систему биндингов и улучшенную интеграцию с современными .NET-стэками.
🤖 GitHub
@csharp_ci
🧠 Задача на C#: "Сбалансированное стандартное отклонение"
Условие
Дан список чисел
Нужно определить: существует ли такой индекс, при котором массив можно разделить на две части, и стандартные отклонения этих частей отличаются не более чем на `epsilon` (например, 0.1).
Пример:
Формат функции:
Решение:
Пример использования:
Что проверяет задача:
• знание статистики и работы со стандартным отклонением
• навыки эффективной работы с коллекциями
• аккуратность при вычислениях с
• понимание требований к длине выборки для корректной статистики
@csharp_1001_notes
Условие
Дан список чисел
List<double>
— это одномерное распределение значений. Нужно определить: существует ли такой индекс, при котором массив можно разделить на две части, и стандартные отклонения этих частей отличаются не более чем на `epsilon` (например, 0.1).
Пример:
var data = new List<double> { 1.0, 2.0, 3.0, 6.0, 9.0 };
// Разделение после 2 → [1.0, 2.0], [3.0, 6.0, 9.0]
// std_left ≈ 0.707, std_right ≈ 3.0 → ❌ слишком большая разница
Формат функции:
public static bool HasBalancedStdSplit(List<double> data, double epsilon = 0.1)
Решение:
using System;
using System.Collections.Generic;
using System.Linq;
public class StatUtils
{
public static bool HasBalancedStdSplit(List<double> data, double epsilon = 0.1)
{
int n = data.Count;
if (n < 4) return false;
for (int i = 2; i <= n - 2; i++)
{
var left = data.Take(i).ToList();
var right = data.Skip(i).ToList();
double stdLeft = StandardDeviation(left);
double stdRight = StandardDeviation(right);
if (Math.Abs(stdLeft - stdRight) <= epsilon)
return true;
}
return false;
}
private static double StandardDeviation(List<double> values)
{
double mean = values.Average();
double sumSquares = values.Sum(v => Math.Pow(v - mean, 2));
return Math.Sqrt(sumSquares / (values.Count - 1));
}
}
Пример использования:
class Program
{
static void Main()
{
var data = new List<double> { 2, 4, 4, 4, 5, 5, 7, 9 };
bool result = StatUtils.HasBalancedStdSplit(data, 0.5);
Console.WriteLine($"Можно ли сбалансировать: {result}");
}
}
Что проверяет задача:
• знание статистики и работы со стандартным отклонением
• навыки эффективной работы с коллекциями
• аккуратность при вычислениях с
double
• понимание требований к длине выборки для корректной статистики
@csharp_1001_notes
⚙️ `[EnumeratorCancellation]` в C# — критически важный атрибут для корректной отмены в `IAsyncEnumerable`
В .NET асинхронные итераторы (`IAsyncEnumerable<T>`) стали мощным инструментом для потоковой обработки данных. Но если вы используете
⚠️ Проблема: токен есть, но он бесполезен
Допустим, вы пишете такой метод:
Выглядит нормально, но есть подвох: при отмене токен не передаётся в `MoveNextAsync()`, то есть итерация может продолжаться, даже если вызвавшая сторона уже вызвала
💣 Последствия
• Фоновая загрузка продолжается после отмены
• Зависшие соединения, неосвобождённые ресурсы
• Непредсказуемое поведение в
• Сложные баги и плохая отзывчивость приложений
✅ Решение:
Правильно будет вот так:
📌 Атрибут
🧪 Как проверить
Если метод реализован без
Если с атрибутом — отмена сработает как положено, и итерация завершится немедленно.
🛠 Best Practices
✔ Всегда используйте
✔ Внутри итератора:
- Вызывайте
- Оборачивайте вложенные
✔ Не используйте токен «для галочки» — он должен влиять на поведение итератора
✔ Добавляйте юнит‑тесты на отмену, особенно если вы работаете с I/O, API или базами данных
📎 Заключение
Асинхронные итераторы — мощь. Но без
Одна строка — и вы защищены:
📚 Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html
🧠 Если ты пишешь на C# и используешь
📌 Читать
@csharp_1001_notes
В .NET асинхронные итераторы (`IAsyncEnumerable<T>`) стали мощным инструментом для потоковой обработки данных. Но если вы используете
CancellationToken
без специального атрибута [EnumeratorCancellation]
, ваш код может вести себя некорректно и утекать ресурсы. Разберёмся подробно.⚠️ Проблема: токен есть, но он бесполезен
Допустим, вы пишете такой метод:
public async IAsyncEnumerable<string> FetchItems(CancellationToken cancellationToken)
{
foreach (var id in ids)
{
var item = await GetDataAsync(id);
yield return item;
}
}
Выглядит нормально, но есть подвох: при отмене токен не передаётся в `MoveNextAsync()`, то есть итерация может продолжаться, даже если вызвавшая сторона уже вызвала
cancellationToken.Cancel()
.💣 Последствия
• Фоновая загрузка продолжается после отмены
• Зависшие соединения, неосвобождённые ресурсы
• Непредсказуемое поведение в
await foreach
• Сложные баги и плохая отзывчивость приложений
✅ Решение:
[EnumeratorCancellation]
Правильно будет вот так:
public async IAsyncEnumerable<string> FetchItems(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
await foreach (var item in LoadFromDb().WithCancellation(cancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
yield return item;
}
}
📌 Атрибут
[EnumeratorCancellation]
сообщает компилятору, что токен должен быть передан в реализацию `MoveNextAsync()` итератора. Без этого атрибута токен проигнорируется.🧪 Как проверить
var cts = new CancellationTokenSource();
await foreach (var item in FetchItems(cts.Token))
{
if (item == "stop") cts.Cancel();
}
Если метод реализован без
[EnumeratorCancellation]
, цикл может не остановиться. Если с атрибутом — отмена сработает как положено, и итерация завершится немедленно.
🛠 Best Practices
✔ Всегда используйте
[EnumeratorCancellation]
, если метод IAsyncEnumerable<T>
принимает CancellationToken
✔ Внутри итератора:
- Вызывайте
ThrowIfCancellationRequested()
- Оборачивайте вложенные
await foreach
или асинхронные методы в .WithCancellation(token)
✔ Не используйте токен «для галочки» — он должен влиять на поведение итератора
✔ Добавляйте юнит‑тесты на отмену, особенно если вы работаете с I/O, API или базами данных
📎 Заключение
Асинхронные итераторы — мощь. Но без
[EnumeratorCancellation]
ваш токен отмены просто не работает. И это не очевидно, пока вы не столкнётесь с багом, когда ресурсы не освобождаются, или цикл не завершается.Одна строка — и вы защищены:
[EnumeratorCancellation] CancellationToken token
📚 Источник: https://bartwullems.blogspot.com/2025/04/asyncenumerable-in-c-importance-of.html
🧠 Если ты пишешь на C# и используешь
IAsyncEnumerable
— знай: токен без атрибута = фейковая отмена.📌 Читать
@csharp_1001_notes
🧠 C# Задача: “Ловушка замыкания в цикле”
📜 Условие:
Посмотри на этот код и скажи, что он выведет:
❓ Вопросы:
1. Что напечатает программа?
2. Почему результат может удивить?
3. Как исправить код, чтобы получить
⚠️ Подвох:
- Переменная
- Когда цикл завершится,
---
### ✅ Ожидаемый вывод:
🛠️ Исправление:
Чтобы каждая лямбда захватывала свою копию `i`, нужно добавить промежуточную переменную:
Теперь вывод будет:
🎯 Что проверяет задача:
- Знание механики замыканий в C#
- Понимание разницы между значениями и ссылками в замыкании
- Умение отлаживать неожиданные результаты в LINQ и делегатах
📜 Условие:
Посмотри на этот код и скажи, что он выведет:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
var actions = new List<Action>();
for (int i = 0; i < 5; i++)
{
actions.Add(() => Console.Write(i + " "));
}
foreach (var action in actions)
{
action();
}
}
}
❓ Вопросы:
1. Что напечатает программа?
2. Почему результат может удивить?
3. Как исправить код, чтобы получить
0 1 2 3 4
?⚠️ Подвох:
- Переменная
i
захватывается по ссылке всеми лямбдами в List<Action>
, а не копируется в момент добавления.- Когда цикл завершится,
i == 5
, и все лямбды обращаются к одному и тому же `i`, уже равному 5
.---
### ✅ Ожидаемый вывод:
5 5 5 5 5
🛠️ Исправление:
Чтобы каждая лямбда захватывала свою копию `i`, нужно добавить промежуточную переменную:
for (int i = 0; i < 5; i++)
{
int copy = i;
actions.Add(() => Console.Write(copy + " "));
}
Теперь вывод будет:
0 1 2 3 4
🎯 Что проверяет задача:
- Знание механики замыканий в C#
- Понимание разницы между значениями и ссылками в замыкании
- Умение отлаживать неожиданные результаты в LINQ и делегатах
🚀 Wissance.WebApiToolkit: Быстрое создание REST и GRPC API на .NET
Если устал каждый раз писать одинаковый CRUD — этот toolkit тебя спасёт.
С помощью [Wissance.WebApiToolkit](https://github.com/Wissance/WebApiToolkit) можно создать полноценный REST или GRPC API почти без усилий.
● Что умеет:
- Минимум кода — CRUD-контроллер ≈ 10 строк
- BULK-операции: обновление/удаление сразу нескольких объектов
- Поддержка Entity Framework, EdgeDB и других хранилищ через
- Автогенерация GRPC-сервисов
- Встроенная пагинация, фильтрация, сортировка
- Поддержка Swagger (c версии 1.6.0)
● Архитектура построена на 5 слоях:
● Пример CRUD-контроллера:
● Установка:
🔗 WeatherControl — полная интеграция с EF и EdgeDB
⭐ Проект open-source:
github.com/Wissance/WebApiToolkit
Если устал каждый раз писать одинаковый CRUD — этот toolkit тебя спасёт.
С помощью [Wissance.WebApiToolkit](https://github.com/Wissance/WebApiToolkit) можно создать полноценный REST или GRPC API почти без усилий.
● Что умеет:
- Минимум кода — CRUD-контроллер ≈ 10 строк
- BULK-операции: обновление/удаление сразу нескольких объектов
- Поддержка Entity Framework, EdgeDB и других хранилищ через
IModelManager
- Автогенерация GRPC-сервисов
- Встроенная пагинация, фильтрация, сортировка
- Поддержка Swagger (c версии 1.6.0)
● Архитектура построена на 5 слоях:
Entity
→ DTO
→ Factory
→ Manager
→ Controller
● Пример CRUD-контроллера:
[ApiController]
public class BookController : BasicCrudController<BookDto, BookEntity, int, EmptyAdditionalFilters>
{
public BookController(BookManager manager)
{
Manager = manager;
_manager = manager;
}
private readonly BookManager _manager;
}
● Установка:
dotnet add package Wissance.WebApiToolkit
🔗 WeatherControl — полная интеграция с EF и EdgeDB
⭐ Проект open-source:
github.com/Wissance/WebApiToolkit
🔥 From C# to Rust: 42-дневный челлендж от Chris Woody Woodruff
Chris Woodruff, экспериментающий .NET-разработчик, объявил старт своего 42-дневного пути погружения в Rust — язык системного программирования, совмещающий производительность, безопасность и отсутствие null:contentReference[oaicite:0]{index=0}.
🎯 Цели проекта
- Жить и дышать Rust — по одному уроку в день.
- Противостоять строгому borrow checker.
- Осознанно учиться и делиться выводами от лица C#-разработчика.
🛠 Что ожидается изучить
- Владение памятью, шаблоны, трейты, времена жизни (`lifetimes`).
- Яркие сравнения Rust и C#: синтаксис, ownership vs GC, ошибки компилятора:contentReference[oaicite:2]{index=2}.
- Краткие ежедневные отражения из .NET-мира.
📅 Примерный план на 42 дня
1. День 1–7: Почему Rust? Установка, cargo new vs dotnet new, "Hello, World!", переменные, функции:contentReference[oaicite:4]{index=4}.
2. День 8–14: Неделя владения — темы: ownership, borrowing, borrow checker:contentReference[oaicite:5]{index=5}.
3. День 15–42: Структуры, перечисления (`enum`), match, Option<T>, Result<T, E>, модули, ошибки, трейты, дженерики, лямбды и многое другое.
💬 Голос из сообщества
> «What happens when a C# dev swaps null for Option, garbage collection for ownership… You get 42 days of brain‑bending, compiler‑fighting…»
✨ Подытожим
- Проект идёт с апреля 2025 года, уже опубликованы десятки дневных эссе.
- Каждая запись по мотивам реального опыта: «why won’t this compile?!», сравнения с привычным C#.
- В финале — обзор полученного опыта, личные инсайты и примеры рабочего CLI‑приложения на Rust:contentReference[oaicite:8]{index=8}.
🚀 Готовы бросить вызов себе и глубже понять Rust?
Следите за дневником Woody и за входом в мир безопасных без‑GC систем прямо с .NET-опытов!
🔗 Подробнее: From C# to Rust: A 42-Day Developer Challenge
https://woodruff.dev/from-c-to-rust-a-42-day-developer-challenge/
Chris Woodruff, экспериментающий .NET-разработчик, объявил старт своего 42-дневного пути погружения в Rust — язык системного программирования, совмещающий производительность, безопасность и отсутствие null:contentReference[oaicite:0]{index=0}.
🎯 Цели проекта
- Жить и дышать Rust — по одному уроку в день.
- Противостоять строгому borrow checker.
- Осознанно учиться и делиться выводами от лица C#-разработчика.
🛠 Что ожидается изучить
- Владение памятью, шаблоны, трейты, времена жизни (`lifetimes`).
- Яркие сравнения Rust и C#: синтаксис, ownership vs GC, ошибки компилятора:contentReference[oaicite:2]{index=2}.
- Краткие ежедневные отражения из .NET-мира.
📅 Примерный план на 42 дня
1. День 1–7: Почему Rust? Установка, cargo new vs dotnet new, "Hello, World!", переменные, функции:contentReference[oaicite:4]{index=4}.
2. День 8–14: Неделя владения — темы: ownership, borrowing, borrow checker:contentReference[oaicite:5]{index=5}.
3. День 15–42: Структуры, перечисления (`enum`), match, Option<T>, Result<T, E>, модули, ошибки, трейты, дженерики, лямбды и многое другое.
💬 Голос из сообщества
> «What happens when a C# dev swaps null for Option, garbage collection for ownership… You get 42 days of brain‑bending, compiler‑fighting…»
✨ Подытожим
- Проект идёт с апреля 2025 года, уже опубликованы десятки дневных эссе.
- Каждая запись по мотивам реального опыта: «why won’t this compile?!», сравнения с привычным C#.
- В финале — обзор полученного опыта, личные инсайты и примеры рабочего CLI‑приложения на Rust:contentReference[oaicite:8]{index=8}.
🚀 Готовы бросить вызов себе и глубже понять Rust?
Следите за дневником Woody и за входом в мир безопасных без‑GC систем прямо с .NET-опытов!
🔗 Подробнее: From C# to Rust: A 42-Day Developer Challenge
https://woodruff.dev/from-c-to-rust-a-42-day-developer-challenge/
SQL_cheatsheet.pdf
754.9 KB
⚡️ SQL-шпаргалка, которая выручит в интервью, проекте и проде
Полный мастер-гайд по SQL в одном PDF: практичные примеры, чёткие объяснения и никакой воды.
Что внутри:
• 💬 Создание баз, таблиц и изменение схем
• 💬 Запросы любого уровня сложности: JOIN, GROUP BY, HAVING, PARTITION
• 💬 Подзапросы, CTE, оконные функции: ROW_NUMBER, RANK, DENSE_RANK
• 💬 VIEW, временные таблицы и работа с дубликатами
• 💬 Даты, строки, преобразования и агрегации
• 💬 Очистка данных, разбиение по разделителям
• 💬 UNION, INTERSECT, EXCEPT — управление сложными выборками
Затрагиваются и продвинутые кейсы:
• Парсинг адресов
• Кастомная сортировка
• Использование ISNULL и COALESCE
🧠 Это не просто набор команд — это концентрат боевого SQL-опыта.
Подходит для:
➡️ Подготовки к SQL-интервью
➡️ BI и аналитики
➡️ Web-разработки с базами
➡️ Встраивания SQL в проекты на Python, Go, Java и других языках
Полный мастер-гайд по SQL в одном PDF: практичные примеры, чёткие объяснения и никакой воды.
Что внутри:
• 💬 Создание баз, таблиц и изменение схем
• 💬 Запросы любого уровня сложности: JOIN, GROUP BY, HAVING, PARTITION
• 💬 Подзапросы, CTE, оконные функции: ROW_NUMBER, RANK, DENSE_RANK
• 💬 VIEW, временные таблицы и работа с дубликатами
• 💬 Даты, строки, преобразования и агрегации
• 💬 Очистка данных, разбиение по разделителям
• 💬 UNION, INTERSECT, EXCEPT — управление сложными выборками
Затрагиваются и продвинутые кейсы:
• Парсинг адресов
• Кастомная сортировка
• Использование ISNULL и COALESCE
🧠 Это не просто набор команд — это концентрат боевого SQL-опыта.
Подходит для:
➡️ Подготовки к SQL-интервью
➡️ BI и аналитики
➡️ Web-разработки с базами
➡️ Встраивания SQL в проекты на Python, Go, Java и других языках
🧠 Задача для .NET разработчиков: «Загадочная утечка памяти в ASP.NET Core приложении»
🧩 Уровень: Senior .NET / Backend Engineer
🎯 Цель: Найти и устранить причину роста памяти без падений и исключений
📍 Ситуация:
У вас — высоконагруженное API на ASP.NET Core (.NET 8), работающее под Linux в контейнере.
Сервис обрабатывает тысячи запросов в минуту. Мониторинг показывает:
- Память растёт стабильно, но не освобождается
- GC работает, но не очищает выделенную память
-
- Приложение не падает, но хост начинает свапать и тормозить
- При перезапуске — память очищается, но через 2–3 часа снова заполняется
❗ В логах — тишина, ошибок нет. Библиотеки:
---
🧩 Твоя задача:
1. Почему .NET GC может не освобождать LOH, даже при работе GC?
2. Какие действия вызывают накопление в LOH?
3. Как можно отследить, какие объекты скапливаются в памяти?
4. Чем опасен повторный вызов
5. Как корректно использовать
💡 Подсказка:
- LOH начинается с объектов > 85,000 байт
- Часто виноваты: большие строки, сериализация, `ToString()`, 🧠 Задача для .N🧠 Задача🧠 Задача
- Задача для .NETможет хранить сильные ссылки бесконечно, если не задано время жизни
- Частое создание
🧩 Уровень: S— может удерживать сокеты в TIME_WAIT и загонять GC в ступор
🛠 Решение:
1. Запускаем профилировщик:
2. Смотрим типы с самым большим retained size:
→ В коде — сериализация в JSON огромных объектов без ограничения глубины
3. Находим участок с
4. Исправления:
- Добавить настройки сериализации:
- Ограничить
- Использовать
5. Альтернатива: перейти на
📌 Вывод:
Даже без явных ошибок .NET-приложение может стабильно "утекать" в LOH — через сериализацию, кэш или неправильную работу с потоками. Только анализ дампа памяти и правильная конфигурация GC и кешей помогут найти такие проблемы.
@csharp_1001_notes
🧩 Уровень: Senior .NET / Backend Engineer
🎯 Цель: Найти и устранить причину роста памяти без падений и исключений
📍 Ситуация:
У вас — высоконагруженное API на ASP.NET Core (.NET 8), работающее под Linux в контейнере.
Сервис обрабатывает тысячи запросов в минуту. Мониторинг показывает:
- Память растёт стабильно, но не освобождается
- GC работает, но не очищает выделенную память
-
dotnet-counters
показывает рост в LOH (Large Object Heap)- Приложение не падает, но хост начинает свапать и тормозить
- При перезапуске — память очищается, но через 2–3 часа снова заполняется
❗ В логах — тишина, ошибок нет. Библиотеки:
Newtonsoft.Json
, HttpClient
, MemoryCache
, EF Core
.---
🧩 Твоя задача:
1. Почему .NET GC может не освобождать LOH, даже при работе GC?
2. Какие действия вызывают накопление в LOH?
3. Как можно отследить, какие объекты скапливаются в памяти?
4. Чем опасен повторный вызов
HttpClient
или StringBuilder
без очистки? 5. Как корректно использовать
MemoryCache
, чтобы избежать утечек?💡 Подсказка:
- Часто виноваты: большие строки, сериализация, `ToString()`,
-
- Частое создание
🧩 Уровень: S
🛠 Решение:
1. Запускаем профилировщик:
dotnet-gcdump collect -p <PID>
dotnet-gcdump analyze dump.gcdump
2. Смотрим типы с самым большим retained size:
List<string>
, byte[]
, MemoryStream
→ В коде — сериализация в JSON огромных объектов без ограничения глубины
3. Находим участок с
JsonConvert.SerializeObject(hugeObject)
без MaxDepth
4. Исправления:
- Добавить настройки сериализации:
new JsonSerializerSettings { MaxDepth = 5, ReferenceLoopHandling = Ignore }
- Ограничить
MemoryCache
по размеру:
new MemoryCache(new MemoryCacheOptions { SizeLimit = 100_000_000 });
- Использовать
HttpClientFactory
вместо new HttpClient()
на каждый запрос5. Альтернатива: перейти на
System.Text.Json
с Utf8JsonWriter
— меньше аллокаций📌 Вывод:
Даже без явных ошибок .NET-приложение может стабильно "утекать" в LOH — через сериализацию, кэш или неправильную работу с потоками. Только анализ дампа памяти и правильная конфигурация GC и кешей помогут найти такие проблемы.
@csharp_1001_notes
Forwarded from C# (C Sharp) programming
🚀 Вышел .NET 10 Preview 5 — с улучшениями на всех фронтах!
🛠️ В этом обновлении Microsoft прокачала:
• Runtime — улучшена производительность и управление памятью
• C# — новые языковые фичи для более выразительного кода
• ASP.NET Core — оптимизация рендеринга и поддержки HTTP
• Blazor — упрощена работа с интерактивными компонентами
• MAUI — ускорены сборки и улучшена поддержка платформ
• + расширены инструменты диагностики и безопасности
✅ Почему стоит обратить внимание
Серьёзные улучшения в производительности и безопасность
Новые фичи как в Runtime, так и в C#, веб-фреймворках и UI (MAUI)
Продолжение активного развития с учётом обратной связи сообщества
📌 Подробности
📌 Скачать
.NET 10 уже сейчас выглядит как одно из самых амбициозных обновлений в экосистеме.
@csharp_ci
🛠️ В этом обновлении Microsoft прокачала:
• Runtime — улучшена производительность и управление памятью
• C# — новые языковые фичи для более выразительного кода
• ASP.NET Core — оптимизация рендеринга и поддержки HTTP
• Blazor — упрощена работа с интерактивными компонентами
• MAUI — ускорены сборки и улучшена поддержка платформ
• + расширены инструменты диагностики и безопасности
✅ Почему стоит обратить внимание
Серьёзные улучшения в производительности и безопасность
Новые фичи как в Runtime, так и в C#, веб-фреймворках и UI (MAUI)
Продолжение активного развития с учётом обратной связи сообщества
📌 Подробности
📌 Скачать
.NET 10 уже сейчас выглядит как одно из самых амбициозных обновлений в экосистеме.
@csharp_ci
🌺 Radzen Blazor Components — 90+ UI-компонентов для Blazor. Этот набор открытых компонентов позволяет быстро собирать интерфейсы на Blazor без зависимостей от JavaScript-фреймворков. Все элементы нативные для Blazor, написанные на C#, что обеспечивает полную интеграцию с экосистемой .NET.
Проект активно развивается: новые компоненты появляются регулярно, а не ждут квартальных релизов. Для коммерческой разработки доступна платная подписка с расширенной поддержкой, но базовая функциональность остаётся бесплатной под лицензией MIT.
🤖 GitHub
@csharp_ci
Проект активно развивается: новые компоненты появляются регулярно, а не ждут квартальных релизов. Для коммерческой разработки доступна платная подписка с расширенной поддержкой, но базовая функциональность остаётся бесплатной под лицензией MIT.
🤖 GitHub
@csharp_ci
⚡️ Если ты запускаешь десяток терминалов для старта приложения
С .NET Aspire можно запускать backend, frontend и все зависимости одновременно — быстро и удобно!
Смотри, как это сделать: justkeepcoding.tech/blog/integrating-angular-into-dotnet-aspire
С .NET Aspire можно запускать backend, frontend и все зависимости одновременно — быстро и удобно!
Смотри, как это сделать: justkeepcoding.tech/blog/integrating-angular-into-dotnet-aspire
🗂️ Entity Framework Core — ORM нового поколения для работы с БД. Этот инструмент от Microsoft кардинально меняет подход к взаимодействию с реляционными и NoSQL базами данных.
Для работы инструмент предоставляет мощный слой абстракции, позволяя работать с данными как с объектами, автоматизируя CRUD-операции и миграции схемы. EF Core поддерживает широкий пласт СУБД: от классических SQL Server и PostgreSQL до документоориентированной Cosmos DB. Для SQLite-разработчиков есть отдельный оптимизированный провайдер Microsoft.Data.Sqlite.
🤖 GitHub
Для работы инструмент предоставляет мощный слой абстракции, позволяя работать с данными как с объектами, автоматизируя CRUD-операции и миграции схемы. EF Core поддерживает широкий пласт СУБД: от классических SQL Server и PostgreSQL до документоориентированной Cosmos DB. Для SQLite-разработчиков есть отдельный оптимизированный провайдер Microsoft.Data.Sqlite.
🤖 GitHub
Forwarded from C++ Academy
This media is not supported in your browser
VIEW IN TELEGRAM
🚀 Разработчик показал движок на C, который работает в 14 раз быстрее Unity в браузере — и теперь доступна онлайн-демо.
Многие не поверили в заявленную разницу в производительности, поэтому он выложил демо в открытый доступ. Сравнение проводится с реальным Unity-проектом, выложенным на GitHub.
🛠️ C-движок демонстрирует:
• Существенно более высокую FPS в браузере
• Минимальную просадку при рендеринге
• Низкий overhead по сравнению с WebAssembly-сборкой Unity
💬 Автор пока не решил, выкладывать ли исходники C-версии — рассматривает вариант лицензии CC (non-commercial).
🔗 Демо: https://cgamedev.com/
🔗 Код: https://github.com/gabrieldechichi/unity_webglperftest
@cpluspluc
Многие не поверили в заявленную разницу в производительности, поэтому он выложил демо в открытый доступ. Сравнение проводится с реальным Unity-проектом, выложенным на GitHub.
🛠️ C-движок демонстрирует:
• Существенно более высокую FPS в браузере
• Минимальную просадку при рендеринге
• Низкий overhead по сравнению с WebAssembly-сборкой Unity
💬 Автор пока не решил, выкладывать ли исходники C-версии — рассматривает вариант лицензии CC (non-commercial).
🔗 Демо: https://cgamedev.com/
🔗 Код: https://github.com/gabrieldechichi/unity_webglperftest
@cpluspluc
👶 Junior developer пишет:
🧑 Middle developer пишет:
🧓 Senior developer пишет:
🤔 Почему так происходит?
👉 Потому что булевы переменные — просты по сути, но часто используются неинтуитивно, что делает код запутанным и плохо поддерживаемым.
Вот 7 простых правил, как работать с булевыми значениями в C# и резко улучшить читаемость вашего кода:
1. 🚫 Избегайте двойных отрицаний
❌
✅
❌
✅
❌
✅
Двойные отрицания сбивают с толку и делают логику трудной для чтения.
2. ✅ Используйте понятные префиксы
✅
✅
✅
Префиксы мгновенно раскрывают назначение переменной.
3. 🔤 Предпочитайте единственное число
❌
✅
Единственное число делает значение ясным и конкретным.
4. 🎯 Используйте прилагательные для описания состояния
❌
✅
Булевы переменные должны описывать состояние, а не действие.
5. ⏱ Используйте настоящее время
❌
✅
Текущие состояния — проще и универсальнее в коде.
6. 🔁 Принцип раннего возврата (Return Early)
Пишите условия и булевы проверки так, чтобы код читался сверху вниз, как история — коротко, логично, понятно.
7. ⚠️ Не передавайте булевы параметры
❌
✅
Используйте перечисления или именованные константы — они понятны без документации.
📌 Вывод:
Хорошие имена булевых переменных — это не косметика, а основа читаемости и архитектурной чистоты.
Хорошо названный
💬 А ты какие правила используешь для наименования булевых переменных? Делись в комментариях 👇
notInactive
, tempBool
🧑 Middle developer пишет:
hadSubscriptionOnceUponATime
🧓 Senior developer пишет:
hasSubscription
, isActive
🤔 Почему так происходит?
👉 Потому что булевы переменные — просты по сути, но часто используются неинтуитивно, что делает код запутанным и плохо поддерживаемым.
Вот 7 простых правил, как работать с булевыми значениями в C# и резко улучшить читаемость вашего кода:
1. 🚫 Избегайте двойных отрицаний
❌
user.IsNotActive
✅
user.IsActive
❌
user.HasNoDept
✅
user.HasDept
❌
creditCard.IsNotExpired
✅
creditCard.IsExpired
Двойные отрицания сбивают с толку и делают логику трудной для чтения.
2. ✅ Используйте понятные префиксы
✅
Is
: user.IsActive
✅
Has
: user.HasDept
✅
Should
: order.ShouldBeCanceled
Префиксы мгновенно раскрывают назначение переменной.
3. 🔤 Предпочитайте единственное число
❌
areUsers
✅
hasUsers
Единственное число делает значение ясным и конкретным.
4. 🎯 Используйте прилагательные для описания состояния
❌
CancelOrder
✅
IsOrderCanceled
Булевы переменные должны описывать состояние, а не действие.
5. ⏱ Используйте настоящее время
❌
card.WasExpired
✅
card.IsExpired
Текущие состояния — проще и универсальнее в коде.
6. 🔁 Принцип раннего возврата (Return Early)
Пишите условия и булевы проверки так, чтобы код читался сверху вниз, как история — коротко, логично, понятно.
7. ⚠️ Не передавайте булевы параметры
❌
SendEmail(true)
✅
SendEmail(SendMode.Immediate)
Используйте перечисления или именованные константы — они понятны без документации.
📌 Вывод:
Хорошие имена булевых переменных — это не косметика, а основа читаемости и архитектурной чистоты.
Хорошо названный
isActive
понятнее, чем любые комментарии и тесты.💬 А ты какие правила используешь для наименования булевых переменных? Делись в комментариях 👇
[Best Practice] Явная конфигурация приложений ASP.NET Core
В большинстве существующих .NET-проектов конфигурация оказывается неочевидной, хотя в экосистеме .NET уже есть всё необходимое для ясной и понятной настройки ASP.NET Core веб-приложений с DI.
Как устроена конфигурация ASP.NET Core
- Источники (в порядке приоритета):
1. Host configuration
2.
3.
4. User secrets (в среде Development)
5. переменные окружения
6. аргументы командной строки
При дублировании ключей побеждает источник, указанный позже :contentReference[oaicite:0]{index=0}.
Выбор способа доступа к настройкам
- Через
- Через
Предпочтение паттерну Options даёт типобезопасный доступ к группам настроек и делает их использование очевидным :contentReference[oaicite:1]{index=1}.
Где хранить разные параметры
- `appsettings.json` — общие настройки (без секретов).
- `appsettings.{Environment}.json` — переопределения для конкретного окружения.
- User Secrets (`secrets.json`) — локальные секреты (пароли, ключи API); не используйте
- Azure Key Vault — производственные секреты через
- Переменные окружения и CLI — для срочных или разовых переопределений.
Рекомендации по внедрению
- Избегайте дублирования ключей — задавайте значение только там, где оно действительно меняется.
- В README укажите, что разработчикам нужно получить
- В IaC-скриптах чётко обозначьте необходимые секреты и параметры для каждого окружения.
Преимущества подхода
- Новым участникам проекта легко разобраться в конфигурации — каждый ключ встречается в одном месте.
- Возрастает поддерживаемость и прозрачность настроек.
- Упрощается автоматизация развёртывания (IaC): сразу видно, какие секреты и параметры требуются.
Читать
В большинстве существующих .NET-проектов конфигурация оказывается неочевидной, хотя в экосистеме .NET уже есть всё необходимое для ясной и понятной настройки ASP.NET Core веб-приложений с DI.
Как устроена конфигурация ASP.NET Core
- Источники (в порядке приоритета):
1. Host configuration
2.
appsettings.json
3.
appsettings.{Environment}.json
4. User secrets (в среде Development)
5. переменные окружения
6. аргументы командной строки
При дублировании ключей побеждает источник, указанный позже :contentReference[oaicite:0]{index=0}.
Выбор способа доступа к настройкам
- Через
IConfiguration
- Через
IOptions<T>
/ IOptionsMonitor<T>
Предпочтение паттерну Options даёт типобезопасный доступ к группам настроек и делает их использование очевидным :contentReference[oaicite:1]{index=1}.
Где хранить разные параметры
- `appsettings.json` — общие настройки (без секретов).
- `appsettings.{Environment}.json` — переопределения для конкретного окружения.
- User Secrets (`secrets.json`) — локальные секреты (пароли, ключи API); не используйте
appsettings.json
или appsettings.Development.json
для них :contentReference[oaicite:2]{index=2}. - Azure Key Vault — производственные секреты через
builder.Configuration.AddAzureKeyVault(...)
:contentReference[oaicite:3]{index=3}. - Переменные окружения и CLI — для срочных или разовых переопределений.
Рекомендации по внедрению
- Избегайте дублирования ключей — задавайте значение только там, где оно действительно меняется.
- В README укажите, что разработчикам нужно получить
secrets.json
из менеджера паролей и настроить User Secrets. - В IaC-скриптах чётко обозначьте необходимые секреты и параметры для каждого окружения.
Преимущества подхода
- Новым участникам проекта легко разобраться в конфигурации — каждый ключ встречается в одном месте.
- Возрастает поддерживаемость и прозрачность настроек.
- Упрощается автоматизация развёртывания (IaC): сразу видно, какие секреты и параметры требуются.
Читать