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

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

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

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

РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead
Download Telegram
👩‍💻 Совместное использование настроек сборки в нескольких .NET-проектах: на заметку C#-разработчику

#dotnet #csharp #tip by Dave Callan
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
🥳 Новый формат .NET-решения .slnx теперь доступен в последней превью-версии Rider

Этот формат находится в режиме превью в Visual Studio, а теперь еще и в Rider. Кажется, с новым форматом улучшена читаемость и возможность слияния (mergeability). Выше — пример различий по сравнению с существующим форматом для простого решения.

#dotnet #csharp #tip by Dave Callan
🎉46👍12🔥41🤔1
🤔FluentValidation: прекратите проверять правила при первой ошибке

По умолчанию он проверяет все правила и объединяет сообщения об ошибках. Более эффективно устанавливать CascadeMode либо на уровне класса, либо на уровне цепочки правил, особенно при использовании MustAsync и асинхронных операций.

#dotnet #csharp #tip by Saeed Esmaeelinejad
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍11🤔1👾1
🤔 Как можно аннотировать основной конструктор атрибутом?

Ранее, если у записи/класса/структуры было несколько конструкторов, возникала проблема с десериализацией, так как необходимо было указать атрибут JsonConstructor в основном конструкторе.

Начиная с C# 12, можно использовать method attribute target для указания конструктора☝️

#dotnet #csharp #tip by Oleg Kyrylchuk
👍10🥰2
🔒🔥 В .NET 9 появится новый тип Lock()

Отличный вариант для выделенного типа lock, поскольку это дает нам способ более четко выразить намерение нашего кода.

#dotnet #tip by Steven Giesel
👍50🥱161🔥1
💡 Parameter Object Pattern

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

Очень полезно, когда группа параметров часто используется повторно.

#dotnet #csharp #tip by Dave Callan
😁23👍12🥱8👾3
🤔 Согласитесь, что глубоко вложенный код трудно читать?

В методах с большим количеством вложений можно использовать подход Early Return и Guard Clause, чтобы сделать код более удобным для чтения.

#dotnet #csharp #tip by Dave Callan
👍44🥱35💯7🌚2
👆 Кстати, в EF 9 представлен новый удобный способ заполнения базы данных начальными данными.

#efcore #dotnet #tip by Nabi Karampour
👏39👍10🔥6🥰3
💡 BenchmarkDotNet в действии: простой пример для C#-разработчика

#dotnet #tip by Dave Callan
👍333🔥2🥱2
💡 Кстати, ExecuteUpdate поддерживает обновление complex типов в Entity Framework 9

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

#dotnet #efcore #tip by Oleg Kyrylchuk
🔥18🤔1
🚀 Сравнение производительности конкатенации строк в .NET 9

Есть и другие подходы, когда нам нужна ещё более высокая производительность, но из распространённых подходов, показанных ниже, StringJoin выигрывает.

#dotnet #csharp #tip by Dave Callan
👍25👏3👾2
⚙️ Когда Hash Join быстрее Nested Loops

Внутри SQL-движка соединение таблиц — это не магия, а конкретный алгоритм. Сравним два подхода к соединению таблиц.

Nested Loops работает буквально так, как звучит: берём строку из первой таблицы и ищем совпадения во второй. Если вторая таблица имеет подходящий индекс, поиск по нему будет очень быстрым, и такой алгоритм блестяще справляется с задачей маленькое соединяется с большим.

Hash Join подходит там, где Nested Loops захлёбывается. Он сначала строит хэш-таблицу по одной из входных таблиц, а затем пробегается по второй и ищет совпадения через хэш-функцию. Это даёт огромный выигрыш, когда нужно соединить два больших набора данных, и когда индексов для ускорения поиска нет. Цена такого подхода — расход памяти.

В итоге — если речь идёт о маленьком наборе строк против большого и есть индекс, Nested Loops окажется быстрее. Но если обе таблицы крупные и индексы не спасают, Hash Join чаще всего становится оптимальным выбором.

💬 Как вы бы ответили на такой вопрос на собеседовании?

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91
Что выведет код

Пишите свои ответы в комментариях 👇

Для любознательных ответ такой: 333

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🚩 Задача с собеса: пират и сундуки

Представьте, что вы пират и у вас есть 12 закрытых сундуков. Все они полны золотых монет, но один — фейковый: в нём только песок. Золото тяжелее, песок легче. У вас есть большие весы без гирь, и всего три взвешивания, чтобы вычислить пустышку.

Как решить эту задачу:

1. Делим сундуки на группы по 6 штук. Взвешиваем. Берём ту группу, где вес меньше.

2. Снова делим на группы, но теперь по 3. Взвешиваем. Берём ту тройку, где легче.

3. Сравниваем внутри этой тройки два сундука. Лёгкий сундук и будет с песком. Если сундуки одинаковые по весу, но с песком тот, что остался.

Задача решается бинарным поиском.

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍234👏4😁2
💪 Разминка перед выходными

Есть код:
var dict = new Dictionary<object, string>();

dict[1] = "int";
dict[1L] = "long";
dict[1.0] = "double";

Console.WriteLine(dict.Count);
Console.WriteLine(dict[1 ]);


Что выведет код? Пишите в комменты 👇

Ответь спрячем здесь:
3
int


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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🤔52
🚩 Задача с собеса: контейнер с водой

Ваша задача — выбрать две вертикальные линии на плоскости, чтобы вместе с осью X они образовали контейнер, в который поместится максимум воды. Даны высоты этих линий в массиве.

Как действовать:

1. Ставим два указателя: один — на начало, второй — на конец массива.

2. Считаем объем текущего контейнера: ширина между указателями умножается на минимальную из двух высот.

3. Двигаем указатель с меньшей высотой внутрь. Если обе высоты равны — можно сдвигать любой.

4. Запоминаем максимум, повторяем шаги, пока указатели не встретятся.

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

Пример реализации:
public int MaxArea(int[] h)
{
int l = 0, r = h.Length - 1, m = 0;
while (l < r)
{
m = Math.Max(m, (r - l) * Math.Min(h[l], h[r]));
if (h[l] < h[r]) l++; else r--;
}
return m;
}


➡️ Попробовать на литкоде

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82
✏️ Задача с собеса: квадраты отсортированного массива

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

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

1. Обрабатываем два края массива (left и right), сравниваем их квадраты.

2. Наибольший квадрат записываем в конец результирующего массива.

3. Сдвигаем соответствующий указатель — либо left, либо right.

4. В конце получаем отсортированный массив квадратов.

Решение с двумя указателями:
public int[] SortedSquares(int[] nums) {
int n = nums.Length;
int[] result = new int[n];
int left = 0, right = n - 1, pos = n - 1;

while (left <= right) {
int leftSq = nums[left] * nums[left];
int rightSq = nums[right] * nums[right];

if (leftSq > rightSq) {
result[pos] = leftSq;
left++;
} else {
result[pos] = rightSq;
right--;
}
pos--;
}
return result;
}


➡️ Попробовать на литкоде

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
7❤‍🔥6🥱2
🚩 Задача с собеса

Задача: дана строка s и строка p. Необходимо найти все начальные индексы подстрок в s, которые являются анаграммами строки p.

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

Пример:
Input: s = "cbaebabacd", p = "abc"
Output: [0, 6]

Объяснение:
Подстрока с индекса 0 - "cba", анаграмма "abc".
Подстрока с индекса 6 - "bac", анаграмма "abc".


Оптимальное решение использует технику скользящего окна с подсчетом частот символов.

1. Подсчитываем количество и частоту всех символов в строке p
2. Создаем скользящее окно размером со строку p в строке s
3. Для каждой позиции окна сравниваем частоты символов с эталоном
4. При совпадении добавляем индекс в результат

Код:
public class Solution 
{
public IList<int> FindAnagrams(string s, string p)
{
List<int> result = new List<int>();

if (s.Length < p.Length)
return result;

// Массивы для подсчета частот символов (26 букв английского алфавита)
int[] pCount = new int[26];
int[] windowCount = new int[26];

// Подсчитываем частоты в строке p и первом окне
for (int i = 0; i < p.Length; i++)
{
pCount[p[i] - 'a']++;
windowCount[s[i] - 'a']++;
}

// Проверяем первое окно
if (AreEqual(pCount, windowCount))
result.Add(0);

// Скользим окном по строке s
for (int i = p.Length; i < s.Length; i++)
{
// Добавляем новый символ справа
windowCount[s[i] - 'a']++;

// Удаляем старый символ слева
windowCount[s[i - p.Length] - 'a']--;

// Проверяем текущее окно
if (AreEqual(pCount, windowCount))
result.Add(i - p.Length + 1);
}

return result;
}

// Вспомогательный метод для сравнения массивов частот
private bool AreEqual(int[] arr1, int[] arr2)
{
for (int i = 0; i < 26; i++)
{
if (arr1[i] != arr2[i])
return false;
}
return true;
}
}


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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩32🔥2💯2👾2
🔄 Как развернуть связный список

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

У вас есть цепочка узлов: 1 → 2 → 3 → 4 → 5. Каждый узел хранит значение и ссылку на следующий элемент. Задача — перевернуть все стрелки: 1 ← 2 ← 3 ← 4 ← 5.

Главная сложность здесь не в алгоритме, а в работе с указателями. Стоит перезаписать ссылку неправильно — и вы теряете доступ к остальной части списка. Именно поэтому многие решения проваливаются на первой попытке.

Итеративное решение: три указателя

Самый надёжный подход — использовать три указателя, которые двигаются по списку синхронно.

• prev отслеживает предыдущий узел
• curr указывает на текущий обрабатываемый узел
• next сохраняет следующий узел, чтобы не потерять его при развороте

Код:
public ListNode ReverseList(ListNode head)
{
ListNode prev = null;
ListNode curr = head;

while (curr != null)
{
ListNode next = curr.next; // сохраняем следующий
curr.next = prev; // разворачиваем стрелку
prev = curr; // двигаем prev
curr = next; // двигаем curr
}

return prev;
}


Рекурсивное решение

Если вам нравятся рекурсивные решения, есть и такой вариант:
public ListNode ReverseList(ListNode head)
{
if (head == null || head.next == null)
return head;

ListNode newHead = ReverseList(head.next);
head.next.next = head;
head.next = null;

return newHead;
}


Попробуйте решить задачу сами, прежде чем смотреть готовый код. Нарисуйте список на бумаге, отследите движение указателей вручную. Это единственный способ понять, что происходит.

➡️ Решить задачу

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7🙏2👾1
✏️ Как заработать на всех взлётах цены акций

Дан массив цен акций по дням. Нужно найти максимальную прибыль, совершая любое количество сделок купли-продажи. Одновременно можно держать только одну акцию.

Пример:
Цены: [7, 1, 5, 3, 6, 4]
Ответ: 7

Покупаем за 1, продаём за 5 (прибыль 4). Покупаем за 3, продаём за 6 (прибыль 3). Итого — 7.

Алгоритм

Самый простой подход — жадный алгоритм. Если завтра цена выше, чем сегодня — покупаем сегодня и продаём завтра. Собираем прибыль с каждого роста цены.

Представьте график цен: вам нужно получить прибыль со всех участков, где график идёт вверх. Неважно, сколько это будет сделок — каждый рост приносит деньги.

Почему это работает

Если цена растёт три дня подряд (например, 1 → 3 → 5), то неважно, продавать ли каждый день или держать до конца.

Код:
public class Solution 
{
public int MaxProfit(int[] prices)
{
if (prices == null || prices.Length < 2)
return 0;

int totalProfit = 0;

for (int i = 1; i < prices.Length; i++)
{
// Если цена выросла — берём эту прибыль
if (prices[i] > prices[i - 1])
{
totalProfit += prices[i] - prices[i - 1];
}
}

return totalProfit;
}
}


Или ещё компактнее:
public class Solution 
{
public int MaxProfit(int[] prices)
{
int profit = 0;

for (int i = 1; i < prices.Length; i++)
{
profit += Math.Max(0, prices[i] - prices[i - 1]);
}

return profit;
}
}


Жадный подход здесь безупречен: захватываем каждый рост, игнорируем падения. Никаких сложных расчётов оптимальных точек — только простая логика и максимальная прибыль.

➡️ Попробовать решить

Чтобы щёлкать такие задачи нужно знать алгоритмы. Подтянуть такую базу поможет наш курс по алгоритмам. До конца октября скидка 40%

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

#dotnet_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4👍1