Библиотека шарписта | C#, F#, .NET, ASP.NET
22.2K subscribers
2.68K photos
41 videos
85 files
4.99K links
Все самое полезное для C#-разработчика в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/b60af5a4

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
📎 ValueTask в публичном API

ValueTask часто хвалят за экономию памяти. Но если использовать его в публичном API, потребители могут не оценить такой шаг.

Вопрос: чем так плох ValueTask в публичном API? Он же снизит аллокации

Ответ: у нас в канале с вопросами с собесов

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3😢1
🎯 Нестандартные форматы резюме

Листайте карточки и подбирайте вариант резюме под свои навыки. В комментах можете поделиться своими проектами 👇

➡️ В статье ещё два формата

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁7👍5🤔2
LangGraph vs Semantic Kernel: архитектура агентов

В .NET мире популярен Semantic Kernel, но индустрия движется к графовым подходам. LangGraph реализует паттерн, где агент — это не просто цепочка плагинов, а граф с состоянием.

Архитектурные преимущества:

— цикличность: нативная поддержка циклов (ReAct pattern);
— state management: управление контекстом похоже на работу с сессиями;
— human-in-the-loop: возможность поставить граф на паузу, получить апрув человека и продолжить.

Курс по архитектуре уже стартовал.

Записаться на курс

Смотреть первую лекцию бесплатно
👍61
📎 Фабрика HttpClient в .NET

В .NET для HTTP-запросов фабрика IHttpClientFactory упрощает создание клиентов, интегрируется с DI и решает проблемы вроде утечек сокетов.

Фабрика кэширует обработчики сообщений, управляет их временем жизни и добавляет логирование.

Зачем нужна фабрика

HttpClient из Framework 4.5 часто создают вручную, но это приводит к проблемам: сокеты не освобождаются, DNS не обновляется. Фабрика решает это через пул обработчиков с лайфтаймом в 2 минуты по умолчанию.

Она регистрируется через AddHttpClient в IServiceCollection и дает доступ к CreateClient. Короткоживущие клиенты подходят для большинства случаев, в отличие от долгоживущих с PooledConnectionLifetime.

Предупреждение: если нужны куки, лучше обойтись без фабрики из-за шаринга CookieContainer.

Способы использования

Разработчики выбирают между базовым, именованными, типизированными клиентами или сгенерированными через Refit.

В базовом варианте инжектят IHttpClientFactory и вызывают CreateClient для каждого запроса. Это просто для рефакторинга старого кода.

Именованные клиенты настраивают по имени из конфига, с базовым URI и заголовками вроде User-Agent:
builder.Services.AddHttpClient("MyClient", client =>
{
client.BaseAddress = new Uri("https://api.example.com/");
client.DefaultRequestHeaders.UserAgent.ParseAdd("MyApp");
});


Затем CreateClient("MyClient").

Типизированные удобны для конкретного API: класс принимает HttpClient в конструкторе, фабрика регистрирует его через AddHttpClient<T>.

Логика запросов инкапсулируется в методах класса, DI все подхватывает. IntelliSense работает, нет строковых ключей.

Не используйте в синглтонах: клиент должен быть короткоживущим, иначе DNS не обновится. Лучше именованные или SocketsHttpHandler:
public class ApiService(HttpClient client)
{
public async Task<Todo[]> GetTodos(int id) =>
await client.GetFromJsonAsync<Todo[]>($"todos/{id}");
}


В итоге фабрика делает HTTP-клиенты в .NET предсказуемыми и масштабируемыми. Для прода это как стандарт: меньше багов с соединениями, проще DI.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
6
🧑‍💻 Неявная проверка на null

В C# можно заставить любой класс вести себя в if как в JavaScript: просто if (myObject) и внутри проверка на null. Это работает благодаря перегрузке операторов.

Создайте класс с двумя статическими методами:
public class User
{
public string Name { get; set; }

public static bool operator true(User? user) => user?.Name != null;
public static bool operator false(User? user) => user?.Name == null;
}


Теперь if (user) сработает если имя задано, иначе попадет в else. Компилятор автоматически вызывает нужный оператор при булевом контексте.

Единственный минус: никто не ожидает такого, код становится загадкой для команды. Лучше стандартные is not null или !ReferenceEquals(null, obj).

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15😢12😁6🌚2
7️⃣ Генерация случайных чисел в C#

Класс Random в .NET генерирует псевдослучайные числа для игр, тестов или симуляций. Он работает на основе сида, обычно времени, и дает целые, дробные значения или байты.

Основы класса Random

System.Random создает последовательности чисел через алгоритм. Для простого инта берут Next(min, max), где верхняя граница не включается.

Переиспользуйте один экземпляр, иначе в цикле из-за одинаковых сидов выйдут повторения. Статический или инжектированный через DI вариант подходит для прода:
var rng = new Random();
int число = rng.Next(1, 101); // от 1 до 100


NextDouble возвращает от 0.0 до 1.0, умножьте и сдвиньте для нужного интервала. Байты через NextBytes заполняют массив. Это для тестовых файлов или симуляций.
double температура = rng.NextDouble() * 50 - 10; // от -10 до 40
byte[] буфер = new byte[16];
rng.NextBytes(буфер);


Обычный Random не годится для токенов или паролей, предсказуем при известном сиде. Берите RandomNumberGenerator из System.Security.Cryptography для криптографии.

GetInt32(1, 101) или Fill для байт. В API для ключей всегда крипто-вариант.

Random не потокобезопасен, общий экземпляр сломается. ThreadLocal<Random> создаст по инстансу на поток. Parallel.For с ним работает корректно, без гонок:
var локальныйRng = new ThreadLocal<Random>(() => new Random());
Parallel.For(0, 100, i => {
int значение = локальныйRng.Value!.Next(100);
});


📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍135
📰 Дайджест недели

В .NET-среде штиль, новостей не так много, поэтому вспоминаем лучшее за неделю.

IoT на .NET

ExecuteUpdate и ExecuteDelete

Коты вместо HTTP статусов

10 советов по обустройству вашего рабочего места

Нестандартные форматы резюме

Делитесь в комментах своими инфоповодами недели 👇

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Semantic Kernel или LangGraph?

В мире .NET популярен Semantic Kernel, но глобальный стандарт задаёт LangGraph. Его киллер-фича — явное управление графом выполнения и состоянием (Stateful Graph).

Это позволяет реализовывать сложные паттерны: Human-in-the-loop (человек подтверждает действие), Time Travel (откат состояния назад) и цикличное планирование. Понимание этих принципов пригодится любому разработчику, внедряющему AI.

Записаться на курс

Погружение в архитектуру агентов: Смотрите вводный урок бесплатно.
5🤔1
⚙️ Оптимизация C#: Inlining методов

Инлайнинг (Inlining) — замена вызова метода его телом напрямую в месте вызова. JIT-компилятор делает это автоматически для маленьких методов, которые весят меньше 32 байт.

Зачем это делается

• Убирает overhead вызова метода

• Улучшает локальность кода

• Даёт прирост в 5-7 раз для горячих путей

Пример

Без инлайнинга:
public int Calculate(int a, int b)
{
return Add(a, b) * 2;
}

private int Add(int a, int b) // JIT заинлайнит автоматически
{
return a + b;
}


Что делает JIT:
public int Calculate(int a, int b)
{
return (a + b) * 2; // тело Add() вставлено напрямую
}


Принудительный инлайнинг:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int Multiply(int a, int b)
{
return a * b;
}


Не гадайте — профилируйте. Иногда JIT делает лучше без вашей помощи.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍117🤔1🌚1
🆚 Namespace vs Assembly

Давайте разберёмся, чем отличается namespace от assembly.

Namespace — это логическая организация кода.
Assembly — это физический файл на диске.

Они существуют в разных измерениях и решают разные задачи.

Namespace (пространство имён) — это способ логической группировки классов, интерфейсов и других типов, чтобы избежать конфликтов имён:
namespace MyCompany.PaymentSystem
{
public class PaymentProcessor
{
// ...
}
}

namespace MyCompany.Logging
{
public class Logger
{
// ...
}
}


Зачем нужны namespace

• Без namespace два класса с именем Logger конфликтуют. С namespace можно иметь MyApp.Logger и ThirdPartyLib.Logger одновременно.

• Организация кода по доменам: MyCompany.Ecommerce.Orders, MyCompany.Ecommerce.Products, MyCompany.Ecommerce.Payments.

• Упрощённое использование кода с using

using MyCompany.Ecommerce.Orders;

var order = new Order(); // Вместо: new MyCompany.Ecommerce.Orders.Order()


Можно объявить namespace один раз для всего проекта:
// GlobalUsings.cs
global using System;
global using MyCompany.Core;


Что такое Assembly

Assembly (сборка) — это скомпилированный физический файл на диске .dll или .exe, который содержит IL-код и метаданные.

.exe — приложение, которое можно запустить.
.dll — библиотека для подключения.

Как они связаны

Подключение сборки:
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

Это добавляет assembly в проект.

Использование namespace:
using Newtonsoft.Json;  // Импортируем namespace

var json = JsonConvert.SerializeObject(obj);

//или без using

var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);


Один работает на уровне файлов, другой — на уровне кода.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍8
🚀 Git v2.53

Вышла новая версия системы контроля версий Git v2.53. Разбираем ключевые изменения.

Новые команды

git maintenance is-needed — проверка, нужно ли выполнять задачи обслуживания репозитория.

git repo info --all — показывает расширенную информацию о структуре репозитория.

git blame --diff-algorithm=<algo> — теперь можно выбрать алгоритм сравнения при отслеживании изменений.

Улучшения существующих команд

git replay — теперь выполняет обновление ссылок самостоятельно, не требуя дополнительных команд.

git fast-import — новая опция --signed-commits=strip-if-invalid для удаления невалидных подписей.

git apply и git diff — новый класс ошибок пробелов incomplete-line.

И многие другие мелкие доработки.

➡️ Анонс

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Please open Telegram to view this post
VIEW IN TELEGRAM
😁32👍8👏32🤔1
👨‍💻 Оптимизации с константами

Разберемся, как компилятор превращает понятный код в эффективный и почему лучше расписать «магическое число» на составляющие.

Самая простая оптимизация называется constant folding. Суть в том, что компилятор не будет заставлять процессор каждый раз высчитывать одно и то же. Если вы пишете int result = 10 * 5 + 3 * 2, компилятор прекрасно понимает, что результат всегда будет 56, и именно это число окажется в скомпилированном коде.


public void Example()
{
int result = 10 * 5 + 3 * 2; // Вы пишете это
// Компилятор превращает в:
int result = 56; // Уже посчитано
}


Более интересная оптимизация – constant propagation. Когда вы объявляете константу через const, компилятор запоминает её значение и подставляет его везде, где она используется.

public void ConstantPropagation()
{
const int multiplier = 100;
int value = 42;
int calculated = value * multiplier;

// Компилятор оптимизирует до:
int calculated = value * 100; // multiplier заменен значением
}


Оптимизация строк

С строками всё еще интереснее. Когда вы конкатенируете несколько строковых литералов, компилятор склеивает их в один. Код string message = "Hello" + " " + "World"; превращается в string message = "Hello World";

public void StringOptimization()
{
// Все литералы склеиваются в один
string message = "Hello" + " " + "World";
// Результат: string message = "Hello World";

// С константами тоже работает частично
const string greeting = "Hello";
string name = "Alice";
string message = greeting + " " + name;
// Результат: string message = "Hello " + name;
}


Используйте const там, где это уместно, не бойтесь записывать формулы явно вместо магических чисел – компилятор сам посчитает результат.

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥3🥱2
💡 Фриланс для разработчиков

Вы ищете заказы там, где их ищут все. А локальный бизнес даже не знает о существовании биржи. ИП пишут в чатах «посоветуйте программиста» или листает Авито. Будьте там, где нет толпы.

➡️ В статье 9 способов найти первые проекты без бирж

📍 Навигация: ВакансииЗадачиСобесы

🐸Библиотека шарписта
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰32