Когда несколько потоков одновременно меняют одну переменную без синхронизации, результат становится непредсказуемым
Что важно знать:
• Оборачивай работу с разделяемым состоянием в lock (locker) { ... }
• Держи блокировку минимально короткой: никаких долгих операций, I/O или Thread.Sleep() внутри lock.
• Лишняя синхронизация превращается в узкое место производительности.
Поэтому,
lock помогает писать стабильный и предсказуемый многопоточный код.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤5🤝5🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
Этот репозиторий собрал в одном месте огромное количество полезных материалов по .NET. Удобно, что всё структурировано и разбито по темам, поэтому можно использовать его как для изучения, так и как справочник в работе. Особенно полезен тем, кто хочет разобраться в экосистеме .NET, закрыть пробелы в знаниях и лучше понимать, какие технологии и подходы используются в разработке.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12🔥6👍3
Сидеть и работать в корпорации — страшно, жизнь-то мимо проходит. Уходить строить бизнес — страшно, а вдруг прогорит. Один из вариантов — разрабатывать свой пет-проект по вечерам. Многие успешные компании, например, Twitter, создавались именно так. Это не значит, что ваш проект обязательно заработает миллиарды, но заработать больше, чем в найме, и получить ценный опыт — вполне реально.
Перед началом разработки появляется множество вопросов, например:
• Как выбрать идею для пет-проекта?
• Что нужно знать про маркетинг
• Как запуститься и довести до первых продаж не имея бюджета на рекламу?
В телеграм-канале «Твой пет проект», Михаил Табунов делится своим опытом с разработчиками и менеджерами.
Он рассказывает, где искать идею для нового проекта, что нужно знать о маркетинге, как запустить стартап и привлечь первых 10 клиентов, а также о многих других важных вещах.
Подписывайтесь на «Твой пет проект», получайте пользу от практиков рынка!
https://t.me/+8Frwa03ciVlhNTky
Перед началом разработки появляется множество вопросов, например:
• Как выбрать идею для пет-проекта?
• Что нужно знать про маркетинг
• Как запуститься и довести до первых продаж не имея бюджета на рекламу?
В телеграм-канале «Твой пет проект», Михаил Табунов делится своим опытом с разработчиками и менеджерами.
Он рассказывает, где искать идею для нового проекта, что нужно знать о маркетинге, как запустить стартап и привлечь первых 10 клиентов, а также о многих других важных вещах.
Подписывайтесь на «Твой пет проект», получайте пользу от практиков рынка!
https://t.me/+8Frwa03ciVlhNTky
Telegram
Твой пет проект
Канал про то, как создать свой маленький свечной заводик
Пишу про:
- Запуски и как сделать первые 10 продаж
- Прожарка идей
- Кейсы роста и ведения проекта параллельно с работой
Автор - Михаил Табунов - @bossofyourboss
Связь @to_baza_education
Пишу про:
- Запуски и как сделать первые 10 продаж
- Прожарка идей
- Кейсы роста и ведения проекта параллельно с работой
Автор - Михаил Табунов - @bossofyourboss
Связь @to_baza_education
Фильтруем пользователей по домену email через LINQ!
Допустим, у нас есть список пользователей, и нужно достать только email-адреса на gmail.com.
Создадим простую модель:
Подготовим данные:
Можно пройтись циклом и вручную собрать результат:
Но через LINQ это читается короче:
Select достаёт из пользователя только email.
Where оставляет адреса с нужным доменом.
В результате получим:
Такой подход удобно использовать для фильтрации клиентов, подписчиков, заявок, логов, доменов, тегов и любых списков объектов.
Если регистр может отличаться, лучше явно указать сравнение:
Select() + Where() это удобная связка LINQ, когда нужно достать поле и отфильтровать его по условию.
➡️ C# Ready | #практика
Допустим, у нас есть список пользователей, и нужно достать только email-адреса на gmail.com.
Создадим простую модель:
public record User(string Name, string Email);
Подготовим данные:
var users = new List<User>
{
new("Alex", "alex@gmail.com"),
new("Maria", "maria@company.com"),
new("Bob", "bob@gmail.com")
};
Можно пройтись циклом и вручную собрать результат:
var result = new List<string>();
foreach (var user in users)
{
if (user.Email.EndsWith("@gmail.com"))
{
result.Add(user.Email);
}
}
Но через LINQ это читается короче:
var result = users
.Select(user => user.Email)
.Where(email => email.EndsWith("@gmail.com"))
.ToList();
Select достаёт из пользователя только email.
Where оставляет адреса с нужным доменом.
В результате получим:
alex@gmail.com
bob@gmail.com
Такой подход удобно использовать для фильтрации клиентов, подписчиков, заявок, логов, доменов, тегов и любых списков объектов.
Если регистр может отличаться, лучше явно указать сравнение:
email.EndsWith(
"@gmail.com",
StringComparison.OrdinalIgnoreCase
)
Select() + Where() это удобная связка LINQ, когда нужно достать поле и отфильтровать его по условию.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4🔥3
Напоминалка по исключениям в C#!
Например, NullReferenceException часто появляется при обращении к объекту, который равен null, а ArgumentNullException обычно используют, когда в метод передали обязательный аргумент без значения.
На картинке иерархия исключений в C#: Exception, SystemException, ApplicationException, ArgumentException, IOException и другие популярные типы ошибок.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Например, NullReferenceException часто появляется при обращении к объекту, который равен null, а ArgumentNullException обычно используют, когда в метод передали обязательный аргумент без значения.
На картинке иерархия исключений в C#: Exception, SystemException, ApplicationException, ArgumentException, IOException и другие популярные типы ошибок.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤5🔥3
Почему для времени события часто лучше DateTimeOffset, а не DateTime?
В C# часто пишут так:
Но DateTime.Now зависит от локального времени сервера.
Если приложение работает в разных часовых поясах, в Docker, в облаке или просто переезжает на другой сервер, это может привести к путанице.
Для моментов времени чаще удобнее использовать:
DateTimeOffset хранит не только дату и время, но и смещение относительно UTC.
Это делает значение понятнее при логах, событиях, API, заказах, платежах и аудите.
А для отображения пользователю время уже можно переводить в его часовой пояс отдельно.
Для хранения момента события DateTimeOffset.UtcNow часто безопаснее, чем DateTime.Now.
➡️ C# Ready | #совет
В C# часто пишут так:
var createdAt = DateTime.Now;
Но DateTime.Now зависит от локального времени сервера.
Если приложение работает в разных часовых поясах, в Docker, в облаке или просто переезжает на другой сервер, это может привести к путанице.
Для моментов времени чаще удобнее использовать:
var createdAt = DateTimeOffset.UtcNow;
DateTimeOffset хранит не только дату и время, но и смещение относительно UTC.
Это делает значение понятнее при логах, событиях, API, заказах, платежах и аудите.
А для отображения пользователю время уже можно переводить в его часовой пояс отдельно.
Для хранения момента события DateTimeOffset.UtcNow часто безопаснее, чем DateTime.Now.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤6🔥6
This media is not supported in your browser
VIEW IN TELEGRAM
На сайте собрана подборка полезных материалов для разработчиков, которые изучают C# и C++ и множество других языков. Здесь можно найти статьи, шпаргалки и обучающие ресурсы по основам синтаксиса, ООП, структурам данных, алгоритмам и ключевым концепциям разработки на этих языках.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤5🔥4
Напоминалка по pattern matching в C#!
Например, case string s проверяет тип и сразу даёт переменную, а FileInfo { Extension: ".html" } позволяет матчить объект по его свойствам.
На картинке основные виды pattern matching: type pattern, property pattern, positional pattern, relational pattern и null pattern.
Сохрани, чтобы не потерять!
➡️ C# Ready | #ресурс
Например, case string s проверяет тип и сразу даёт переменную, а FileInfo { Extension: ".html" } позволяет матчить объект по его свойствам.
На картинке основные виды pattern matching: type pattern, property pattern, positional pattern, relational pattern и null pattern.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤6🔥4
🤖 ChatGPT в твоих руках: от вопроса до результата за минуту
ChatGPT всегда под рукой и готов помочь с работой, учёбой и повседневными задачами. Пока он берёт рутину на себя, у тебя остаётся больше времени на важное.
🤔 Но оформить подписку из России бывает непросто: нужны подходящий способ оплаты и дополнительные шаги.
😉 Не переживай, мы берём оформление на себя. Ты оформляешь заказ и предоставляешь необходимые данные, а мы активируем подписку за 5–15 минут. Иностранная карта и взаимодействие с платёжной системой OpenAI не потребуются.
😎 Оформи заказ и начни пользоваться ChatGPT уже сегодня!
💡 Также помогаем с оформлением других AI-подписок (Claude, Gemini и т.д.).
👉 ChatGPT Store
ChatGPT всегда под рукой и готов помочь с работой, учёбой и повседневными задачами. Пока он берёт рутину на себя, у тебя остаётся больше времени на важное.
🤔 Но оформить подписку из России бывает непросто: нужны подходящий способ оплаты и дополнительные шаги.
😉 Не переживай, мы берём оформление на себя. Ты оформляешь заказ и предоставляешь необходимые данные, а мы активируем подписку за 5–15 минут. Иностранная карта и взаимодействие с платёжной системой OpenAI не потребуются.
💳 Оплата российской картой или через СБП
⚡️ Активация в течение 5–15 минут после получения необходимых данных
🔒 Поддержка на весь срок подписки и помощь при возникновении вопросов
⭐️ Более 3 лет опыта и 15 000+ выполненных заказов
😎 Оформи заказ и начни пользоваться ChatGPT уже сегодня!
💡 Также помогаем с оформлением других AI-подписок (Claude, Gemini и т.д.).
👉 ChatGPT Store
👎5😁1
Считаем количество заказов по статусам через LINQ!
Допустим, есть список заказов, и нужно быстро понять, сколько заказов находится в каждом статусе.
Создадим простую модель:
Подготовим данные:
Можно вручную обновлять словарь:
Но через LINQ это выглядит компактнее:
Результат будет примерно таким:
Такой приём полезен для админок, отчётов, аналитики, логов, платежей, заявок и любых списков, где нужно быстро собрать статистику по категориям.
➡️ C# Ready | #практика
Допустим, есть список заказов, и нужно быстро понять, сколько заказов находится в каждом статусе.
Создадим простую модель:
public record Order(string Status, decimal Amount);
Подготовим данные:
var orders = new List<Order>
{
new("Paid", 1200m),
new("New", 500m),
new("Paid", 300m),
new("Cancelled", 100m)
};
Можно вручную обновлять словарь:
var result = new Dictionary<string, int>();
foreach (var order in orders)
{
if (!result.ContainsKey(order.Status))
{
result[order.Status] = 0;
}
result[order.Status]++;
}
Но через LINQ это выглядит компактнее:
var result = orders
.GroupBy(order => order.Status)
.ToDictionary(g => g.Key, g => g.Count());
GroupBy() собирает заказы в группы по статусу.ToDictionary() превращает эти группы в словарь, где ключ это статус, а значение это количество заказов.Результат будет примерно таким:
Paid -> 2
New -> 1
Cancelled -> 1
Такой приём полезен для админок, отчётов, аналитики, логов, платежей, заявок и любых списков, где нужно быстро собрать статистику по категориям.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5🔥5
Это потокобезопасная очередь для передачи сообщений между задачами без ручных блокировок и сложной синхронизации.
Что важно знать:
• Работает без ручных блокировок и сложных синхронных вызовов.
• Позволяет автоматически замедлять отправку при перегрузке памяти.
• Обеспечивает плавную передачу данных между параллельными задачами.
Так вы получаете готовый «из коробки» механизм асинхронной очереди с естественным управлением нагрузкой без лишнего кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤3👍2
FirstOrDefault() может вернуть null!
В C# часто ищут элемент в коллекции через LINQ:
Если пользователь найден то всё хорошо.
Но если подходящего элемента нет, FirstOrDefault() вернёт значение по умолчанию.
Для ссылочных типов это обычно:
Поэтому такой код может упасть:
Если user оказался null, получим NullReferenceException.
Лучше явно обработать отсутствие результата:
Или выбросить понятную ошибку:
Это особенно важно в API, сервисах, обработчиках команд и бизнес-логике.
➡️ C# Ready | #совет
В C# часто ищут элемент в коллекции через LINQ:
var user = users.FirstOrDefault(u => u.Id == id);
Если пользователь найден то всё хорошо.
Но если подходящего элемента нет, FirstOrDefault() вернёт значение по умолчанию.
Для ссылочных типов это обычно:
null
Поэтому такой код может упасть:
Console.WriteLine(user.Name);
Если user оказался null, получим NullReferenceException.
Лучше явно обработать отсутствие результата:
var user = users.FirstOrDefault(u => u.Id == id);
if (user is null)
{
return;
}
Или выбросить понятную ошибку:
var user = users.FirstOrDefault(u => u.Id == id)
?? throw new InvalidOperationException("User not found");
Это особенно важно в API, сервисах, обработчиках команд и бизнес-логике.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍9🔥4
Почему технические строки не стоит сравнивать через ToLower()?
Для проверки логина, роли или кода часто пишут так:
Код работает во многих случаях, но ToLower() создаёт новую строку и использует правила текущей культуры приложения.
Для обычного текста это может быть полезно. Но логины, роли, ключи конфигурации, HTTP-заголовки и другие технические значения обычно должны сравниваться по стабильным правилам, независимо от языка системы.
Для этого лучше явно указать тип сравнения:
OrdinalIgnoreCase не создаёт промежуточную строку и выполняет регистронезависимое порядковое сравнение. Поведение не изменится после запуска приложения на сервере с другой локалью.
Если же сравнивается текст для пользователя, например названия или элементы поиска, может понадобиться CurrentCultureIgnoreCase.
➡️ C# Ready | #совет
Для проверки логина, роли или кода часто пишут так:
if (role.ToLower() == "admin")
{
GrantAccess();
}
Код работает во многих случаях, но ToLower() создаёт новую строку и использует правила текущей культуры приложения.
Для обычного текста это может быть полезно. Но логины, роли, ключи конфигурации, HTTP-заголовки и другие технические значения обычно должны сравниваться по стабильным правилам, независимо от языка системы.
Для этого лучше явно указать тип сравнения:
if (string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase))
{
GrantAccess();
}
OrdinalIgnoreCase не создаёт промежуточную строку и выполняет регистронезависимое порядковое сравнение. Поведение не изменится после запуска приложения на сервере с другой локалью.
Если же сравнивается текст для пользователя, например названия или элементы поиска, может понадобиться CurrentCultureIgnoreCase.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤6🔥4
Теперь небольшую программу на C# можно запустить прямо из одного файла!
В этой статье:
• Как работают File-Based Apps в .NET 10
• Как запустить .cs-файл без создания отдельного проекта
• Каким способом подключать NuGet-пакеты и дополнительные настройки
• Когда такой формат удобен для скриптов, автоматизации и быстрых экспериментов
Получается знакомая простота скриптовых языков, но с возможностями C# и всей экосистемой .NET.
➡️ C# Ready | #статья
В этой статье:
• Как работают File-Based Apps в .NET 10
• Как запустить .cs-файл без создания отдельного проекта
• Каким способом подключать NuGet-пакеты и дополнительные настройки
• Когда такой формат удобен для скриптов, автоматизации и быстрых экспериментов
Получается знакомая простота скриптовых языков, но с возможностями C# и всей экосистемой .NET.
Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍6❤5
Почему технические строки не стоит сравнивать через ToLower()?
Для проверки логина, роли или кода часто пишут так:
Код работает во многих случаях, но ToLower() создаёт новую строку и использует правила текущей культуры приложения.
Для обычного текста это может быть полезно. Но логины, роли, ключи конфигурации, HTTP-заголовки и другие технические значения обычно должны сравниваться по стабильным правилам, независимо от языка системы.
Для этого лучше явно указать тип сравнения:
OrdinalIgnoreCase не создаёт промежуточную строку и выполняет регистронезависимое порядковое сравнение. Поведение не изменится после запуска приложения на сервере с другой локалью.
Если же сравнивается текст для пользователя, например названия или элементы поиска, может понадобиться CurrentCultureIgnoreCase.
➡️ C# Ready | #совет
Для проверки логина, роли или кода часто пишут так:
if (role.ToLower() == "admin")
{
GrantAccess();
}
Код работает во многих случаях, но ToLower() создаёт новую строку и использует правила текущей культуры приложения.
Для обычного текста это может быть полезно. Но логины, роли, ключи конфигурации, HTTP-заголовки и другие технические значения обычно должны сравниваться по стабильным правилам, независимо от языка системы.
Для этого лучше явно указать тип сравнения:
if (string.Equals(role, "admin", StringComparison.OrdinalIgnoreCase))
{
GrantAccess();
}
OrdinalIgnoreCase не создаёт промежуточную строку и выполняет регистронезависимое порядковое сравнение. Поведение не изменится после запуска приложения на сервере с другой локалью.
Если же сравнивается текст для пользователя, например названия или элементы поиска, может понадобиться CurrentCultureIgnoreCase.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤4🔥4