GitHub Copilot теперь можно настроить с помощью Instruction Files и Prompt Files, чтобы AI генерировал код в соответствии с вашими стандартами и требованиями проекта.
Файлы с инструкциями задают общие правила для репозитория: стиль кода, соглашения по именам, обязательные тесты, ограничения на изменения и инструкции по CI/CD.
Их удобно использовать для командной работы и open-source-проектов, чтобы все предложения Copilot соответствовали принятым стандартам.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
async void
ломает ваш кодВ C# у async void есть дурная репутация, и не зря. Такой метод не возвращает Task, а значит, его нельзя await-ить, нельзя встроить в пайплайн и невозможно корректно отследить завершение.
Исключения из него не ловятся обычным образом — они пробиваются в синхронизационный контекст или в пул потоков, где легко превращаются в необработанные и могут уронить процесс.
// Контроллер ASP.NET Core
[HttpPost]
public async void Create() { await _svc.DoAsync(); } // Исключения мимо pipeline
// Библиотека
public async void SaveAsync(Item item) { await _repo.Save(item); } // Вызывающему не сконтролировать
Правильно — всегда возвращать Task:
[HttpPost]
public async Task<IActionResult> Create() { await _svc.DoAsync(); return Ok(); }
public Task Invoke(HttpContext ctx) => _next(ctx);
public Task SaveAsync(Item item) => _repo.Save(item);
Единственный сценарий, где async void уместен, — обработчики событий в UI-фреймворках вроде WPF или WinForms, где сигнатура задаётся самим фреймворком. Там приходится мириться, но даже там стоит ловить исключения локально и логировать их.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8❤🔥8
🔢 Когда числа становятся понятными
UnitsNet — .NET-библиотека, которая превращает голые числа в осмысленные физические величины.
Пример: вместо
вы пишете
и работаете уже с километрами в час, милями или узлами — без ручных пересчётов.
В UnitsNet поддерживается более сотни единиц измерения — от времени и массы до температуры и силы. Вам не нужно держать в голове коэффициенты и вручную пересчитывать из одной системы в другую: библиотека сделает это сама.
Ещё один плюс — читаемость кода. Ваши расчёты выглядят как документация: сразу видно, где давление, где скорость, а где длина.
➡️ Попробовать либу
🐸 Библиотека шарписта
#sharp_view
UnitsNet — .NET-библиотека, которая превращает голые числа в осмысленные физические величины.
Пример: вместо
double speed = 27.8;
вы пишете
Speed speed = Speed.FromMetersPerSecond(27.8);
и работаете уже с километрами в час, милями или узлами — без ручных пересчётов.
В UnitsNet поддерживается более сотни единиц измерения — от времени и массы до температуры и силы. Вам не нужно держать в голове коэффициенты и вручную пересчитывать из одной системы в другую: библиотека сделает это сама.
Ещё один плюс — читаемость кода. Ваши расчёты выглядят как документация: сразу видно, где давление, где скорость, а где длина.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
❤31👍11🔥3⚡1
⏱️ Как ускорить асинхронный код в C#
Частая ошибка — писать асинхронные вызовы последовательно:
Каждая операция ждёт предыдущую и если каждый запрос занимает по секунде, общее время = 3 секунды.
А можно иначе:
Все задачи стартуют сразу. Теперь общее время = 1 секунда (ожидание самой длинной операции).
Маленький приём — большая разница во времени выполнения.
🐸 Библиотека шарписта
#sharp_view
Частая ошибка — писать асинхронные вызовы последовательно:
await GetUser();
await GetOrders();
await GetRecommendations();
Каждая операция ждёт предыдущую и если каждый запрос занимает по секунде, общее время = 3 секунды.
А можно иначе:
var userTask = GetUser();
var ordersTask = GetOrders();
var recsTask = GetRecommendations();
await Task.WhenAll(userTask, ordersTask, recsTask);
Все задачи стартуют сразу. Теперь общее время = 1 секунда (ожидание самой длинной операции).
Маленький приём — большая разница во времени выполнения.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍37🥱8⚡1❤1
Когда в приложении нужно обрабатывать поток данных от продюсеров к потребителям, первым делом вспоминают про очереди или ConcurrentQueue. Но в асинхронном мире этого мало. Поэтому в .NET есть каналы.
Канал устроен как пара из продюсера и потребителя. Когда продюсер пишет элемент в канал, он либо сразу уходит к потребителю, либо ждёт, если очередь переполнена. Потребитель, в свою очередь, может ждать новые элементы без блокировки потоков — всё работает на async/await.
Главная сила каналов — балансировка нагрузки.
Ограниченные каналы позволяют держать под контролем количество элементов. Это защищает приложение от перегрузки: если продюсер работает быстрее, чем потребитель, система сама притормозит поток данных.
Неограниченные каналы — вариант попроще, они всегда принимают новые элементы, но это может обернуться непредсказуемым ростом памяти.
Мини-пример:
var channel = Channel.CreateBounded<int>(5);
// producer
_ = Task.Run(async () =>
{
for (int i = 0; i < 10; i++)
{
await channel.Writer.WriteAsync(i);
Console.WriteLine($"Produced {i}");
}
channel.Writer.Complete();
});
// consumer
await foreach (var item in channel.Reader.ReadAllAsync())
{
Console.WriteLine($"Consumed {item}");
}
Почему это лучше, чем ConcurrentQueue? Потому что Channel создан сразу с учётом асинхронности. Вам не нужно городить блокировки и таймеры ожидания — достаточно написать
await reader.ReadAsync()
, и код будет сам по себе масштабироваться без блокировки потоков.#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
❤24👍8🤩4
работа с null всегда была источником ошибок. Каждый хоть раз ловил NullReferenceException в рантайме.
Есть два подхода: старый — вручную проверять null, и новый — использовать nullable reference types с поддержкой компилятора.
Код с ручной проверкой на null:
public string GetUserName(User? user)
{
if (user == null)
return "Anonymous";
return user.Name;
}
Плюсы:
• просто и понятно
• работает везде
Минусы:
• легко забыть проверить
• ошибки проявятся только в рантайме
С включённой фичей #nullable enable компилятор начинает помогать:
public string GetUserName(User? user)
{
return user?.Name ?? "Anonymous";
}
•
User?
явно говорит: объект может быть null• компилятор подсветит, если забыли проверить
• меньше бойлерплейта, больше читаемости
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
1❤🔥5🥱5❤3
🔥 Избавляемся от if-else деревьев
Когда логика программы разрастается, мы часто пишем целые деревья if-else или switch. Но такой код тяжело читать и сопровождать.
Вместо if-ветвей можно использовать паттерн State. Он выносит каждое состояние в отдельный класс. Объект делегирует своё поведение текущему состоянию, а переходы происходят прозрачно.
Код с if'ами:
Код со State:
Теперь добавление нового состояния — просто новый класс, без переписывания всей логики.
🐸 Библиотека шарписта
#sharp_view
Когда логика программы разрастается, мы часто пишем целые деревья if-else или switch. Но такой код тяжело читать и сопровождать.
Вместо if-ветвей можно использовать паттерн State. Он выносит каждое состояние в отдельный класс. Объект делегирует своё поведение текущему состоянию, а переходы происходят прозрачно.
Код с if'ами:
public class Document
{
public string State { get; set; } = "Draft";
public void Publish()
{
if (State == "Draft") State = "Moderation";
else if (State == "Moderation") State = "Published";
else Console.WriteLine("Документ уже опубликован");
}
}
Код со State:
public interface IDocumentState
{
void Publish(Document doc);
}
public class Draft : IDocumentState
{
public void Publish(Document doc) => doc.State = new Moderation();
}
public class Moderation : IDocumentState
{
public void Publish(Document doc) => doc.State = new Published();
}
public class Published : IDocumentState
{
public void Publish(Document doc) => Console.WriteLine("Уже опубликован");
}
public class Document
{
public IDocumentState State { get; set; } = new Draft();
public void Publish() => State.Publish(this);
}
Теперь добавление нового состояния — просто новый класс, без переписывания всей логики.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍14❤5😁3😢3
BitFaster.Caching — это библиотека для in-memory кеша с акцентом на работу в многопоточной среде.
В отличие от стандартного MemoryCache, она предлагает больше контроля над политиками вытеснения и поведением при высокой нагрузке.
Что умеет:
• Потокобезопасные кеши без глобальных блокировок.
• Поддержка LRU и LFU (включая TinyLFU) для выбора стратегии вытеснения.
• Атомарное вычисление значений, чтобы избежать шторма запросов.
• Настраиваемые политики истечения: по времени доступа или записи.
• API-билдер для конфигурации размера и параметров кеша.
Пример:
var cache = CacheBuilder
.NewLru<string, MyObject>()
.WithCapacity(1000)
.ExpireAfterAccess(TimeSpan.FromMinutes(5))
.Build();
var value = cache.GetOrAdd("key", k => new MyObject(k));
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤩5🔥4👍2❤1
Dependency Injection в .NET быстро превращает Program.cs в кашу. В видео показывают, как вынести DI в расширения, структурировать код и упростить регистрацию сервисов с помощью Scrutor.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍9👏2
⚙️ Zero-Allocation LINQ для .NET
LINQ — одна из лучших фич в C#. Она делает код декларативным и читаемым. Но у стандартного System.Linq есть проблема: каждая операция создает кучу объектов и аллокаций
Если у вас миллионы запросов в секунду, эти «маленькие удобства» превращаются в серьёзные проблемы со сборщиком мусора, задержками и падением производительности.
ZLinq — это библиотека, которая реализует все стандартные LINQ-операции (Where, Select, GroupBy, Aggregate, OrderBy и т.д.) без выделения памяти в куче.
Пример:
➡️ GitHub либы
🐸 Библиотека шарписта
#sharp_view
LINQ — одна из лучших фич в C#. Она делает код декларативным и читаемым. Но у стандартного System.Linq есть проблема: каждая операция создает кучу объектов и аллокаций
Если у вас миллионы запросов в секунду, эти «маленькие удобства» превращаются в серьёзные проблемы со сборщиком мусора, задержками и падением производительности.
ZLinq — это библиотека, которая реализует все стандартные LINQ-операции (Where, Select, GroupBy, Aggregate, OrderBy и т.д.) без выделения памяти в куче.
Пример:
// Обычный LINQ
var result = numbers.Where(x => x % 2 == 0).Select(x => x * 2).ToList();
// ZLinq
var result = numbers.AsZEnumerable()
.Where(x => x % 2 == 0)
.Select(x => x * 2)
.ToList();
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔34❤4👍2
Когда нужно проверить строку на пустоту в C# есть два популярных метода:
string.IsNullOrEmpty(str)
возвращает true, если строка равна null или имеет длину 0 ("").string.IsNullOrWhiteSpace(str)
идёт дальше: он также учитывает пробелы, табы и переводы строк. То есть " " будет считаться пустой.Код:
Console.WriteLine(string.IsNullOrEmpty(" ")); // False
Console.WriteLine(string.IsNullOrWhiteSpace(" ")); // True
Если нужно проверить только на null и пустую строку — используйте IsNullOrEmpty. Если важно исключить строки, состоящие только из пробелов или невидимых символов — выбирайте IsNullOrWhiteSpace.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱22👍3😁2❤1
В .NET есть команда создаёт готовый .gitignore, оптимизированный под экосистему.
В нём уже прописаны все типичные исключения: каталоги bin/, obj/, кэш NuGet, файлы публикаций, временные артефакты IDE и прочие служебные данные, которые не должны попадать в репозиторий.
Команда:
dotnet new gitignore
Не нужно искать шаблон на GitHub или копировать его вручную — всё доступно из коробки.
#sharp_view
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4