ar
Feedback
C# 1001 notes

C# 1001 notes

الذهاب إلى القناة على Telegram

Регулярные короткие заметки по C# и .NET. Просто о сложном для каждого. admin - @haarrp

إظهار المزيد
6 539
المشتركون
-324 ساعات
-17 أيام
-230 أيام
أرشيف المشاركات
🚀 Wissance.WebApiToolkit: Быстрое создание REST и GRPC API на .NET Если устал каждый раз писать одинаковый CRUD — этот toolk
🚀 Wissance.WebApiToolkit: Быстрое создание REST и GRPC API на .NET Если устал каждый раз писать одинаковый 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 слоях: EntityDTOFactoryManagerControllerПример 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

Разработчики, девопсы, сисадмины: 📲 внимание, внимание! Похоже, эпоха открытого исходного кода идёт к концу: одна за одной н
Разработчики, девопсы, сисадмины: 📲 внимание, внимание! Похоже, эпоха открытого исходного кода идёт к концу: одна за одной наши любимые бесплатные C#-библиотеки становятся платными. И что же теперь делать? Давайте соберёмся вместе и подумаем. Приглашаем вас на открытую онлайн-дискуссию «Библиотеки C# уходят в платную сферу: конец эры опенсорса?» 📌Узнаете, какие библиотеки уже стали платными и что ждёт экосистему дальше 📌Узнаете, чем конкретно можно заменить ту или иную библиотеку 📌Сможете уменьшить лицензионные риски 📌Сможете вовремя изменить карьерный вектор или поменять архитектуру проектов 📌 Получите экспертные рекомендации по архитектуре и устойчивым решениям Спикеры: 👨‍💻Олег Голенищев – старший разработчик в Directum 👨‍💻Антон Герасименко – ведущий .NET-разработчик. Всем участникам – скидка 7% на любой курс OTUS и подборка альтернативных библиотек с открытым исходным кодом в подарок. 27 мая, 19:00 МСК Бесплатно по записи: https://tglink.io/a87663fba48d Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963. erid: 2W5zFG9Ybix

🧠 C# Задача: “Ловушка замыкания в цикле” 📜 Условие: Посмотри на этот код и скажи, что он выведет:

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 и делегатах

Горизонтальное масштабирование СУБД на примере Greenplum Современные приложения работают с огромными объёмами данных, и рано
Горизонтальное масштабирование СУБД на примере Greenplum Современные приложения работают с огромными объёмами данных, и рано или поздно классические СУБД перестают справляться с нагрузкой. Выход — горизонтальное масштабирование, позволяющее эффективно распределять запросы и хранение по нескольким узлам. 📌 На вебинары вы: — Познакомитесь с концепцией горизонтального масштабирования и почему оно критически важно в высоконагруженных системах. — Разберёте архитектуру СУБД Greenplum — одного из самых мощных решений на базе PostgreSQL для работы с Big Data. — Узнаете, как устроены шардирование, партиционирование, репликация и управление кластерами в Greenplum. — Посмотрите реальные кейсы использования Greenplum в распределённых системах. 👉 Регистрация и подробности о курсе Highload Architect: https://otus.pw/zwUN/?erid=2W5zFGGPcs2 Бесплатное занятие приурочено к старту курса Highload Architect, обучение на котором позволит освоить решения, которые выдерживают большое количество запросов в секунду и правильно оптимизировать работоспособность серверов. Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.

⚙️ `[EnumeratorCancellation]` в C# — критически важный атрибут для корректной отмены в `IAsyncEnumerable` В .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

🎮 Unity-разработчик? Пора на новый уровень! Пройди тест, подтверди свои знания и стань студентом курса: https://otus.pw/WwBW
🎮 Unity-разработчик? Пора на новый уровень! Пройди тест, подтверди свои знания и стань студентом курса: https://otus.pw/WwBW/ Если ты уже знаком с Unity и хочешь систематизировать знания, углубиться в архитектуру и освоить профессиональные практики разработки игр, то это именно то, что тебе нужно. Мы стартуем уже 29 мая! 🧠 Что ты узнаешь: - Применение принципов SOLID и паттернов GRASP на практике - Навыки выявления и устранения антипаттернов в коде - Разработка модульной архитектуры и повторно используемого кода - Создание систем загрузки, сохранения и ИИ - Освоение фреймворков Zenject и LeoECS - Работа с Addressables и подходом Test Driven Development ⏰Скорее проходи вступительный тест и получи выгодное предложение: https://otus.pw/WwBW/ erid: 2W5zFK2mjNg

🧠 Задача на C#: "Сбалансированное стандартное отклонение" Условие Дан список чисел 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

🚀 Silk.NET 3.0: грядущая революция в .NET-графике Сообщество Silk.NET анонсировало работу над третьей версией своего фреймво
🚀 Silk.NET 3.0: грядущая революция в .NET-графике Сообщество Silk.NET анонсировало работу над третьей версией своего фреймворка — амбициозным переосмыслением того, как должны работать низкоуровневые .NET-биндинги для графики и мультимедиа. Особенность проекта всегда заключалась в кроссплатформенности и минимальных накладных расходах при работе с GPU. В 3.0 разработчики обещают переработанную систему биндингов и улучшенную интеграцию с современными .NET-стэками. 🤖 GitHub @csharp_ci

1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟 ИТ-событие, которое нельзя пропустить. Участие бесплатное 6 июня разработчики из российских биг
1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟 ИТ-событие, которое нельзя пропустить. Участие бесплатное 6 июня разработчики из российских бигтехов на практических примерах покажут, как ИИ перестал быть экспериментом и стал частью разработки. В программе: — Больше 40 докладов от известных ученых и ИТ-компаний. — Выступления зарубежных спикеров с индексом Хирша более 50. — Концентрация практических кейсов: как создаются большие проекты с применением AI. — Доклады по архитектуре, бэкенд-разработке и построению ИТ-платформ. — AI-интерактивы и технологические квесты. — Пространство для нетворкинга, …а еще after-party со звездным лайн-апом. Когда: 6 июня Где: Москва, МТС Live Холл и онлайн Регистрация по ссылке

📌 Задача: "Высоконагружённый кэш с автоматической очисткой и конкурентным доступом" ❗️Условие: Реализуйте класс 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.

- ❗ Нельзя полагаться только на фоновую очистку — нужно проверять срок жизни прямо при Get. - ❗ При огромном количестве ключей (`100k+`) может быть узким местом полное сканирование всех записей каждые 30 секунд. - ❗ Нужно уметь корректно завершать работу фонового потока при остановке приложения (`Dispose`). --- ▪️ Вопросы на собеседовании: - Как бы вы модифицировали SmartCache для ограничения размера кэша (например, максимум 10_000 элементов)? - Как сделать очистку более масштабируемой, чтобы не перебирать все ключи сразу? - Как бы вы реализовали приоритетное вытеснение устаревших элементов? ---

🖥Задача: "Высоконагружённый кэш с автоматической очисткой и конкурентным доступом" 📌 Условие: Реализуйте класс 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. --- ▪️ Возможные подводные камни:

⚡️Легкий способ получать свежие обновления и следить за трендами в разработке на вашем языке. Находите свой стек и подписывайтесь: 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

❓Сталкиваетесь с задачами, когда вам нужно выбрать лучший алгоритм, но не понимаете, как анализировать их сложность? Ваш код
Сталкиваетесь с задачами, когда вам нужно выбрать лучший алгоритм, но не понимаете, как анализировать их сложность? Ваш код может быть медленным или неэффективным, и вы не знаете, как это исправить?  📗На открытом вебинаре 21 апреля в 20:00 мск вы освоите важные инструменты для анализа сложности алгоритмов, улучшите свой навык решения алгоритмических задач и на примере простых алгоритмов сортировки и увидите разницу при применении алгоритмов разной степени сложности. ➡️Регистрируйтесь прямо сейчас и получите скидку на большое обучение «C# Developer» по промокоду SHARP_SPEC_4: https://otus.pw/ph5R/?erid=2W5zFJYeybN Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.

Вы используете локальные переменные в LINQ и используете let? 👇 Ключевое слово let позволяет вводить временную переменную пр
Вы используете локальные переменные в LINQ и используете let? 👇 Ключевое слово 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 = … — собираем уникальные категории

Улучшения API OrderedDictionary: новые перегрузки для TryAdd и TryGetValue возвращают позиции индексов для эффективного доступа. Обновление генерации исходного кода JSON: атрибут JsonSourceGenerationOptionsAttribute теперь поддерживает ReferenceHandler для расширенного управления сериализацией.​ Для получения более подробной информации сюда

В третьем предварительном выпуске .NET 10 Preview 3, Microsoft сосредоточила внимание на улучшении производительности, удобстве для разработчиков и современных облачных паттернах. Хотя этот выпуск не содержит значимых новых функций, он предлагает значительные усовершенствования в различных областях.​ 🔧 Основные нововведения 🐳 Нативная публикация контейнеров для консольных приложений Теперь консольные приложения могут создавать контейнерные образы с помощью команды:​ 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 напрямую на этих типах, снижая количество выделений памяти. Для получения более подробной информации сюда

Что покажет код, представленный на картинке?
Anonymous voting

photo content

.NET митап в Нижнем Новгороде + трансляция Когда: 21 апреля, 19:00 (мск) Офлайн: КУПНО, регистрация обязательна, число мест о
.NET митап в Нижнем Новгороде + трансляция Когда: 21 апреля, 19:00 (мск) Офлайн: КУПНО, регистрация обязательна, число мест ограничено Онлайн: VK и Youtube, зарегистрируйтесь, чтобы получить ссылки на просмотр/запись. В программе доклады: • О построении распределенных систем и паттерне outbox от Андрея Цветцих (Т-Банк), • О расчете вероятности любого события инструментами .NET от Кирилла Панина (Altenar), • О миграции данных с MS SQL на Postgres SQL от Дмитрия Ершова (Рексофт).