Библиотека шарписта | C#, F#, .NET, ASP.NET
21.7K subscribers
2.89K photos
45 videos
91 files
5.34K links
Все самое полезное для C#-разработчика в одном канале.

Наши курсы: https://clc.to/y3LDtw

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

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

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
📌 Версии версионирования

Какую систему нумерации версий предпочитаете и встречали ли экзотические варианты? Делитесь опытом👇

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

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

#схема
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
👍 Современные помощники для валидации параметров

Помните те времена, когда каждый метод начинался с целой простыни проверок входных параметров? Копипаста if (string.IsNullOrEmpty(...)) была ежедневной рутиной:


public void ProcessUser(string name, string email, int age)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("Value cannot be null or empty.", nameof(name));

if (string.IsNullOrEmpty(email))
throw new ArgumentException("Value cannot be null or empty.", nameof(email));

if (age < 0)
throw new ArgumentOutOfRangeException(nameof(age), "Value must be non-negative.");

// Наконец-то бизнес-логика!
}


Код становился шумным, а реальная логика терялась в океане проверок. Каждый разработчик писал по-своему, сообщения об ошибках отличались, а про опечатки в nameof() вообще молчим.

Теперь всё это превращается в лаконичные однострочники:


public void ProcessUser(string name, string email, int age)
{
ArgumentException.ThrowIfNullOrEmpty(name);
ArgumentException.ThrowIfNullOrEmpty(email);
ArgumentOutOfRangeException.ThrowIfNegative(age);
}


Стандартная библиотека предлагает методы на все случаи жизни:


// Проверки на null
ArgumentNullException.ThrowIfNull(user);

// Числовые диапазоны
ArgumentOutOfRangeException.ThrowIfNegative(temperature);
ArgumentOutOfRangeException.ThrowIfZero(divisor);
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(count);

// Сравнения
ArgumentOutOfRangeException.ThrowIfGreaterThan(progress, 100);
ArgumentOutOfRangeException.ThrowIfLessThan(quantity, 1);
ArgumentOutOfRangeException.ThrowIfEqual(status, Status.Invalid);
ArgumentOutOfRangeException.ThrowIfNotEqual(version, expectedVersion);


Эти методы — не просто синтаксический сахар. Они воплощают принцип fail-fast: обнаруживай проблемы немедленно, не позволяй невалидным данным распространяться по системе.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍236👾4❤‍🔥1
😬 Microsoft показала ещё один кусочек будущего .NET

Вышел .NET 11 Preview 7. Апдейт затронул почти весь стек: C#, Runtime, SDK, ASP.NET Core, EF Core, MAUI, F# и Windows Forms.

Главное изменение это перевод NativeAOT в режим по умолчанию в CLI ради заметно более быстрого старта приложений.

Из языка подъехали фичи C# 15, среди них паттерны union и помеченные break и continue для управления вложенными циклами.

В библиотеки добавили десятичные типы по стандарту IEEE 754 и шифрование паролем для ZIP.


Стабильный .NET 11 ожидается в ноябре, а пока Preview 7 можно использовать как полигон: проверить свои проекты на новом SDK и заранее найти проблемы с совместимостью.

👍 — тестирую превью
🔥 — до релиза даже не трогаю

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥45👍6🤩2
🔖 Помеченные break и continue в C# 15. Выход из вложенных циклов без костылей

Знакомая боль. Есть вложенные циклы, и из внутреннего нужно прервать или продолжить внешний. Обычный break выходит только из ближайшего цикла, поэтому приходилось заводить булев флаг и проверять его на каждом уровне, либо прыгать через goto. И то и другое замусоривает логику.

В C# 15 у циклов появились метки, а break и continue научились указывать, какой именно цикл они имеют в виду. Метка ставится прямо на нужный цикл.


outer: for (int row = 0; row < grid.Height; row++)
{
for (int col = 0; col < grid.Width; col++)
{
if (grid[row, col].IsBlocked)
continue outer;

if (grid[row, col].IsGoal)
break outer;
}
}


🔵 Читается ровно так, как задумано. continue outer переходит к следующей итерации внешнего цикла, а break outer полностью выходит из него, минуя остаток внутреннего. Никаких флагов и подсчёта уровней.

Пара нюансов. break можно нацелить и на цикл, и на switch, а continue только на цикл, ведь продолжать switch нечего. И метка привязывается именно к тому циклу, перед которым стоит, поэтому двусмысленности, как с goto, здесь нет.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥36🥱43
🤨 NativeAOT. Что значит скомпилировать .NET в нативный код заранее

NativeAOT снова на слуху, потому что в .NET 11 Preview 7 его сделали режимом по умолчанию в CLI ради быстрого старта. Разберём, что это вообще такое и чем отличается от привычной модели.

Обычно .NET работает так. Код на C# компилируется в промежуточный язык IL, а в нативные инструкции его переводит JIT уже во время запуска. Это гибко, но у первого запуска есть цена на разогрев, а вместе с приложением едет рантайм, который всё это исполняет.

NativeAOT переворачивает подход. Компиляция в машинный код происходит заранее, на этапе сборки. На выходе вы получаете самодостаточный нативный исполняемый файл, внутри которого нет ни IL, ни JIT. Приложению не нужен установленный рантайм, оно просто запускается.


🔴 Что это даёт. Старт почти мгновенный, ведь разогревать JIT нечего. Память на старте меньше, а размер развёртывания компактнее, потому что лишнее вырезается при сборке. Для консольных утилит, бессерверных функций и контейнеров, где важен быстрый холодный старт, это большой плюс.

🔴 Есть и цена. Раз всё решается на этапе сборки, в рантайме нельзя генерировать код и сильно ограничена рефлексия, ведь компилятор должен заранее видеть, что используется. Часть библиотек, завязанных на динамику, просто не поедет. Плюс сборка идёт под конкретную платформу, и кросс-компиляция не всегда проста.

NativeAOT отлично ложится на маленькие быстрые сервисы и утилиты, где ценны холодный старт и компактность. Для больших приложений с тяжёлой рефлексией и динамической загрузкой сначала проверьте совместимость. Включается это в файле проекта.


<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>


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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍4
🖍 NuGet сокращает зависимость от долгоживущих API-ключей

NuGet продолжает ужесточать безопасность публикации пакетов. Один из главных шагов — переход от постоянных API-ключей к короткоживущим credentials через Trusted Publishing.

Вместо хранения секрета в CI/CD workflow получает OIDC-токен, NuGet проверяет его и выдаёт временный API-ключ. Такой ключ действует около часа и затем становится недействительным.

Для CI/CD это означает простую вещь: вместо регулярной ручной ротации секретов можно настроить Trusted Publishing и вообще убрать долгоживущий NuGet API key из пайплайна.


Для обычных scoped API keys NuGet по-прежнему позволяет задавать срок действия самостоятельно.

💡 Если у вас есть автоматическая публикация пакетов, сейчас хороший момент проверить, не хранится ли долгоживущий NuGet API key прямо в CI/CD.

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

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

#async_news
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔4👍1🔥1😢1
🔖 Required + init: обязательные свойства без длинного конструктора

Раньше обязательные свойства часто приходилось передавать через конструктор или проверять уже во время выполнения.

🔵 В C# 11 появился required:


public class User
{
public required string Email { get; init; }
public required string Name { get; init; }
public int Age { get; init; }
}


🔵 Теперь компилятор не позволит создать объект без обязательных свойств:


var user = new User
{
Name = "Ada"
}; // ошибка компиляции


🔵 А такой вариант пройдёт:


var user = new User
{
Email = "ada@x.io",
Name = "Ada"
};


init дополняет эту конструкцию: свойство можно задать при создании объекта, но нельзя изменить обычным присваиванием после инициализации.

Если обязательные свойства заполняются внутри конструктора, можно использовать [SetsRequiredMembers], чтобы сообщить об этом компилятору.

required отвечает за обязательность при создании, а init — за запрет последующего присваивания 💡

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥4👏1
💡 Скрытые копии структур. Зачем нужны readonly struct и in

Структуры передаются по значению — это знают все. Но копия может появиться и там, где её совсем не ожидаешь.
Представьте структуру с обычным, не readonly, методом. Если она находится в readonly-контексте, например в readonly поле или приходит через in, компилятору приходится защищать значение от изменения. При вызове такого метода он может создать защитную копию структуры.

➡️ Для большой структуры в горячем цикле это уже лишняя работа. Решение — явно обозначить неизменяемость:


public readonly struct Point
{
public int X { get; }
public int Y { get; }

public int Sum() => X + Y;
}


Можно пометить readonly и отдельные методы или свойства, если всю структуру сделать неизменяемой нельзя.
in при этом позволяет передавать большую структуру по ссылке без обычного копирования, а readonly-члены помогают избежать защитных копий при работе с такой ссылкой.

Если структура концептуально неизменяемая, readonly struct — хороший выбор по умолчанию. А для больших структур in может снизить стоимость передачи, но его эффект зависит от конкретного сценария


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

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

#il_люминатор
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥2👍1
This media is not supported in your browser
VIEW IN TELEGRAM
Visual Studio умеет превращать JSON в C#-классы за пару кликов

Не нужен онлайн-конвертер. Копируете JSON и в Visual Studio выбираете:


Edit → Paste Special → Paste JSON As Classes


IDE сама сгенерирует классы, включая вложенные объекты и массивы.

Особенно удобно, когда нужно быстро разобраться с ответом незнакомого API или сделать DTO для прототипа.

💡 А после генерации уже стоит привести классы в порядок: переименовать типы, добавить required/init, атрибуты сериализации и убрать лишнее.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩17🥱12😁1
🈶 Паттерны and, or и not. Условия, которые читаются как фраза

Проверки диапазонов в C# легко превращаются в цепочки сравнений с && и ||. Паттерны позволяют записать их компактнее.

С C# 9 условия можно комбинировать прямо внутри pattern matching:


string Grade(int score) => score switch
{
< 0 or > 100 => "некорректно",
>= 90 => "отлично",
>= 60 and < 90 => "нормально",
_ => "плохо",
};


not особенно удобен для проверок:


if (value is not null)
Process(value);

if (obj is not string)
return;


Паттерны можно комбинировать и с проверкой свойств:


bool IsAdultAdmin(User u) =>
u is { Age: >= 18, Role: "admin" };


Вместо нескольких if получаем одно выражение, где условие читается почти как обычная фраза.

💡 Особенно хорошо такой синтаксис работает там, где нужно описать форму данных или диапазон допустимых значений.

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

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

#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍96🌚3