.NET Разработчик
6.75K subscribers
485 photos
5 videos
14 files
2.46K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 2798. #Оффтоп
Утиная Типизация в C# с Помощью Перехватчиков. Часть 2
Некоторое время назад я выложил пост от Steven Giesel о реализации утиной типизации в C# с помощью перехватчиков (interceptors). Тогда это был лишь прототип с множеством недоработок. Теперь же это полноценная библиотека: IfItQuacks.

TL;DR
Объявите интерфейс, пометьте метод атрибутом [DuckTyped] и передавайте в него любой подходящий объект — без базового класса, без явной реализации интерфейса и без каких-либо атрибутов на самих типах:
using IfItQuacks;

public interface INamed
{
string Name { get; }
}

public class Person { public string Name => "Steven"; }
public class Mallard { public string Name => "Donald"; }

public partial class Greeter
{
[DuckTyped]
public string Greet(
INamed first,
INamed second,
string greeting = "Hello")
=> $"{greeting}, {first.Name} and {second.Name}!";
}

Console.WriteLine(new Greeter()
.Greet(new Person(), new Mallard()));
// Hello, Steven and Donald!

Ни Person, ни Mallard не знают об INamed. Генератор кода на этапе компиляции проверяет наличие у обоих типов свойства Name и перенаправляет вызов через небольшой сгенерированный адаптер. Никакой рефлексии, никакого dynamic. Если типы несовместимы, анализатор выдаст ошибку.

Можно также явно привести объекты к интерфейсу, чтобы хранить их:
List<INamed> names = [
Duck.As<INamed>(new Person()),
Duck.As<INamed>(new Mallard())
];

Подробности можно найти в документации. Далее кратко основные моменты.

Анонимные типы — это «утки»
Анонимные типы отлично «крякают» (по сути, то же самое, что предлагает TypeScript):
new Greeter().Greet(
new { Name = "Steven" },
new { Name = "Donald" });


По сути, можно писать свои тесты с «мгновенными моками»:
public interface IPerson
{
string Name { get; }
int Age { get; }
}

public partial class AgeChecker
{
[DuckTyped]
public bool IsAdult(IPerson person)
=> person.Age >= 18;
}

[Test]
public void Should_detect_adults()
{
var checker = new AgeChecker();

Assert.That(
checker.IsAdult(new { Name = "Steven", Age = 90 }), Is.True);
Assert.That(
checker.IsAdult(new { Name = "Baby Duck", Age = 1 }), Is.False);
}


Либо:
IPerson stub = 
Duck.As<IPerson>(new { Name = "Donald", Age = 90 });

List<IPerson> family =
[
Duck.As<IPerson>(new { Name = "Huey", Age = 10 }),
Duck.As<IPerson>(new { Name = "Dewey", Age = 10 }),
Duck.As<IPerson>(new { Name = "Louie", Age = 10 }),
];


Идентичность сохраняется
Адаптеры перенаправляют вызовы методов Equals, GetHashCode и ToString к обёрнутому экземпляру, благодаря чему они корректно работают в словарях и множествах. Кроме того, можно получить доступ к исходному объекту:
var person = new Person();
Duck.As<INamed>(person)
.Equals(Duck.As<INamed>(person)); // true
Duck
.Unwrap(Duck.As<INamed>(person)) is Person; // true


А также поддерживаются:
- Любой интерфейс, включая интерфейсы фреймворков: Duck.As<IDisposable>(x), параметры IEnumerable<T> и т.п.;
- Параметры интерфейса, не требующие утиной типизации (например, ILogger), продолжают принимать реализации, значения null и значения по умолчанию;
- Обобщённые интерфейсы (IContainer<T>) и обобщённые методы [DuckTyped] с выведением аргументов типа;
- События, индексаторы и реализация интерфейса по умолчанию;
- Делегаты, лямбда-выражения и группы методов для интерфейсов с одним методом;
- Статические абстрактные члены и операторы с помощью ограничений утиной типизации (where T : IAddable<T>) - включая обобщённую математику;
- Методы экземпляра и статические методы, ref/out, params, значения по умолчанию и именованные аргументы;
- Нулевая настройка: установите пакет, никаких изменений в файлах проекта не требуется.

Источник: https://steven-giesel.com/blogPost/41599817-4457-441e-b874-1a5c67f4e7cc/if-it-quacks-part-2
👍8
День 2799.
Конференция DotNext 2026. Часть 1
25 и 26 сентября в Москве прошла очередная конференция DotNext. Вернулся и делюсь впечатлениями. Я уже писал, какие доклады хочу посетить, однако, по ходу несколько раз передумал. На этот раз решил посетить несколько воркшопов, т.к. они не записываются на видео, а доклады можно посмотреть в записи позже. Воркшоп отличается от доклада тем, что на нём разбирается конкретный практический пример, а аудитория активно участвует, задавая вопросы или предлагая решения. Раньше они меня пугали своей продолжительностью. Доклады длятся по часу, а воркшоп – это обычно от полутора часов и дольше. ИЧСХ, в начале каждого воркшопа любой докладчик считает своим долгом упомянуть, что времени у нас очень мало 😉. Хочу признать, что я много потерял, не посещая воркшопы раньше. Это отличный опыт практики и командной работы.

Первым был воркшоп от Андрея Цветцих (они с братом Денисом завсегдатаи различных конференций) «Паттерны асинхронного взаимодействия в распределенных системах». Мы разбирали пример реализации сервиса уведомлений (например, по e-mail) о событиях. Как настроить передачу информации в сервис рассылки? Какие данные передавать? Как реализовать гарантии доставки и избежать отправки дублирующих сообщений? Возможно ли реализовать доставку «exactly-once»? Интересно, что здесь нет единственно верного решения. Каждое решение – компромисс со своими плюсами и минусами.

После воркшопа я немного поговорил с Андреем.
- Вы выступаете почти на каждой конференции DotNext и ещё на многих других. Что мотивирует постоянно готовить доклады или воркшопы?
- Мне кажется мотивация комплексная. Когда ты что-то хорошо знаешь, хочется поделиться, двигать индустрию. Я не только разработчик и спикер, я ещё и пользователь систем других. Я хочу, чтобы мне не приходило по сто уведомлялок. Хочу, чтобы заказы, которые делаю на разных сайтах, доходили. И так далее. Это желание поделиться тем, что ты хорошо знаешь. Попутно есть мотивация в том, что приятно просто выступать на сцене, но это скорее такая, побочная. Кроме того, хорошо, когда есть какие-то материалы, на которые можно сослаться. Если несколько раз одно и то же рассказываешь, надоедает. Хочется сказать: «Вот ссылка, посмотрите и потом обсудим». Ну и, как правило, когда ссылку даёшь, с вопросами больше не возвращаются.


Самое смешное, что сразу после разговора с Андреем, дочь мне прямо «в тему» прислала скриншот своего почтового ящика с 30+ одинаковыми письмами (вуз уведомлял о необходимости пройти какой-то тест) 🤦‍♂️

Я поговорил и с другими участниками и докладчиками о том, зачем они посещают конференции. Виктор Дзицкий впервые выступал на DotNext с докладом «Extension Members: новый уровень проектирования .NET API или новый уровень сложности?».
- Во-первых, как прошло?
- Отлично, всё по плану.
- Когда раньше выступал где-то?
- Да, на митапах, но на такой крупной конференции в первый раз, надеюсь не в последний.
- Зачем приезжать на большие конференции и зачем выступать, в чём мотивация?
- В первую очередь для нетворкинга, чтобы общаться с другими спикерами, с другими людьми. Для меня, например, было очень интересно вживую со многими встретиться. Приходили совершенно неожиданные ребята. Например, подошёл товарищ, связанный с моей онлайн деятельностью, говорит: «Слушай, это не ты вёл курсы по
ASP.NET? Я после них устроился на первую работу». Вот такие приятные события. Встретил вживую коллегу, с которым несколько лет работал онлайн и только на DotNext увиделся вживую. Встретил девочку, которая у нас проходила внутреннюю академию, и сейчас живёт и работает в Москве. Встретился, собственно, с программным комитетом и всем .NET-сообществом. Ну и вообще, для меня DotNext – это когда собираются несколько разработчиков из Сургута, Ухты, Севастополя, Москвы и т.д. за одним столом и, как старые друзья, обсуждают общие проблемы. А выступать, во-первых, конечно, какое-то самовыражение. Доказать себе, что ты можешь на таком же уровне соответствовать другим коллегам.
- Ещё будешь делать доклады?
- Конечно, буду.


А вот мнения участников (зрителей).

Константин Овечкин: «Во-первых, классные доклады интересные на современные темы. Во-вторых, много общения с разработчиками, коллегами с другого стека немного, с другими задачами. Всегда очень интересно пообщаться, узнать их мнение, какие задачи они решают. Соответственно, новые знакомства и активности на стендах тоже вполне интересны. Это уже пятая моя конференция. Каждый год я уезжаю максимально довольный, потому что это всегда свежие эмоции. И самое классное на конференциях – сложные темы, которые есть в докладах. Они подстёгивают тебя для дальнейшего развития. Поэтому с удовольствием ждешь следующую конференцию, чтобы принять следующий вызов».

Дмитрий Сорокин: «Я приезжаю на конференции иногда послушать доклады, пообщаться, но в последнее время я на них начал узнавать, что я просто ни хрена не знаю 😊 Как дохожу до каких-то архитектурных решений… То есть, получается, что мне указывают на слабые места, которые нужно подтягивать».

Александр Сашурин: «Потусоваться 😊 Ну, конечно, вот те же хардкорные доклады – это же не цель посидеть в одиночестве послушать. Ты это доклад послушал, а потом его обсудил с разными людьми, со знакомыми или с новыми знакомыми».

Ольга Бондаренко: «Не хватает живого общения в реале, потому что все мы удалёнщики. И реально заинтересованные своей работой люди – они все заняты своей работой. А DotNext, получается, собирает всех людей, энтузиастов, которые заинтересованы в своей профессии. И живое общение с такими людьми – это больше всего меня тут заряжает. Также зачекиниться на всех стендах, обязательно оставить свои контактные данные. Потому что это потенциальные работодатели. <… общий смех, т.к. её тимлид всё это время стоял рядом …>».

Антон Шевченко: «Пообщаться, со знакомыми увидеться. Может, что-то даже интересное расскажут 😊».
👍6
Фото 3 (с) Анатолий Кулаков
1👍12👎3
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
День 2802. #Карьера #Юмор
Секреты Программирования, Известные Только Легендам
Ещё один пост из серии программистских советов, на этот раз менее серьёзный.

Написание кода сегодня обходится дёшево: существует множество инструментов, готовых сделать это за вас. Выдающихся разработчиков отличает умение принимать верные решения. А это умение опирается на привычки, о которых обычно не пишут в учебниках. Большинство таких привычек рождается из ошибок, стоивших кому-то испорченной недели работы. Вы усваиваете их, выпуская код с багами или наблюдая, как старший коллега за минуту исправляет то, на что у вас ушёл целый день.

1. Лучший код — тот, который вы удаляете
Пишите меньше кода, чем, как вам кажется, необходимо. Каждая добавленная строка становится вашей «собственностью» навсегда. Она может сломаться, для неё нужен тест, и когда-нибудь её будет читать другой человек. Чем больше кода, тем больше мест, где могут прятаться баги. Меньше кода — меньше затрат на поддержку и объяснения. Лучший пулл-реквест – тот, в котором удаляется больше строк, чем добавляется.

2. Если что-то сломалось, сначала ищите причину в своём коде
Прежде чем винить чужой код, проверьте то, что написали сами. И чем свежее изменение, тем вероятнее, что ошибка именно в нём. Так вы быстрее найдёте баг и будете выглядеть более компетентным специалистом.

3. Тест, который никогда не падает, ничего не проверяет
Зеленые тесты создают ложное чувство безопасности. И на этом часто обжигаются. Успешный тест бесполезен, если он не падает при поломке кода.
Поэтому намеренно ломайте код, убедитесь, что тест стал красным, а затем исправляйте ошибку.

4. Пишите код для бедолаги, который будет его читать
Компьютер выполнит любой код, а вот человеку придётся в нем разбираться. И этим человеком возможно будете вы. Вы в будущем — когда уже забудете, как всё это работает. Вы будете читать этот код гораздо чаще, чем писать. Так что облегчите себе жизнь. Хитроумный код приятно писать, но мучительно читать. Всегда выбирайте ясность.

5. Нет ничего более постоянного, чем временное решение
Быстрое «грязное» решение, которое вы собираетесь внедрить, переживёт вас в этой компании. Никто не вернётся туда, чтобы привести его в порядок. Следующий разработчик просто построит поверх него новую логику. Как только другой код начинает зависеть от вашего «костыля», его рефакторинг превращается в отдельный проект. Поэтому пишите временное решение так, словно оно должно прослужить 10 лет, — потому что так оно и будет.

6. Оцените срок выполнения… и удвойте его
Если у вас мало опыта в оценке сроков, какую бы оценку вы ни собирались дать — умножайте её на два. Вы представляете себе идеальный сценарий, но работа — это всё, что происходит вокруг него. Тестирование, обработка граничных случаев, ревью, совещания, сбои на демо. Что-то всегда идёт не так. «Первые 90% кода занимают первые 90% времени разработки. Оставшиеся 10% кода занимают вторые 90% времени».

7. Просите о помощи через час, а не через день
Застряли и не продвигаетесь уже час? Спрашивайте. Попытки справиться в одиночку после этого момента тешат лишь ваше самолюбие — и больше ничего.
Старший разработчик в вашей команде наверняка уже сталкивался с такой ошибкой. Один вопрос сэкономит вам часы. Умение вовремя попросить о помощи — это навык. Это признак рассудительности, а не слабости.

8. Если работает — не трогайте
Видите ту уродливую функцию, которую все обходят стороной? Оставьте её в покое. Она выглядит неправильно, потому что выдержала проверку всеми теми граничными случаями, с которыми вы ещё не сталкивались. Каждая странная ветка кода там — это исправленная кем-то ошибка. Этот хаос — живая история проекта. Если всё же приходится вносить правки, меняйте что-то одно и небольшое, тестируйте и наблюдайте за работой прода.

9. Никогда не делайте релиз в пятницу
Никогда не выкатывайте рискованные изменения прямо перед тем, как уйти с работы. Пятница — это классическая ловушка. То же самое касается периодов перед праздниками, длинными выходными или отпуском. Развёртывание требует присмотра. Ошибки проявляются через минуты после запуска, а не через дни. Если просто выкатить обновление и уйти, разгребать проблемы придётся тому, кто остался дежурить. А часто не остаётся никого. Выпускайте обновления в начале дня и в начале недели, пока есть кому помочь.

Итого
Этому не учат на курсах. Такой опыт приобретается ценой собственных ошибок и «шрамов». Или же его можно перенять у того, кто уже заплатил за него высокую цену.

Источник: https://medium.com/javarevisited/9-hidden-coding-secrets-only-great-developers-know-c0ffd93c0b63
👍13
День 2803. #Оффтоп
Чем Заняться, Пока Работают Агенты? У VS Code Есть Ответ

Сейчас большую часть кода за вас пишут агенты. И тут возникает вопрос: чем занять освободившееся время? Можно изучить новый фреймворк, но это подозрительно напоминает работу. К счастью, у команды VS Code нашлась идея получше. Они предложили завести питомца.

Что это?
Это интерактивный персонаж, который располагается над полем ввода в чате. Он реагирует на активность в чате и на ваши действия. Пока агент работает, питомец наблюдает. Раньше вы смотрели на индикатор выполнения, делая вид, что контролируете процесс. Теперь есть с кем разделить это занятие.
Примечание: этот питомец — экспериментальная функция, поэтому он может измениться или исчезнуть. Не привязывайтесь к нему слишком сильно.

Как завести питомца
Введите /vscode-pet в поле ввода чата, чтобы показать или скрыть его. Показать и скрыть — это все обязательства. Не нужны ни график кормления, ни ветеринар (по крайней мере, пока).

Чем заняться
- Кликнуть - чтобы вызвать реакцию. С клавиатуры: нажмите Tab, чтобы перевести на него фокус, а затем Enter или пробел. Да, питомец доступен для управления с клавиатуры.
- Перетаскивать по области чата и оставлять там, где захотите (правда, он падает, если под ним ничего нет).
- Начать перетаскивать и отпустить, чтоб подбросить.
- С помощью клавиш со стрелками «влево» и «вправо» заставлять прыгать.
- С помощью клавиш со стрелками «влево» и «вправо» при удержании Shift – бросать в стену. Да, у авторов своеобразное чувство юмора.

Нажмите правой кнопкой мыши на питомца (или Shift+F10, когда он в фокусе), чтобы открыть контекстное меню, где можно:
- посмотреть достижения,
- отправить побегать,
- изменить размер,
- переключаться между цветовыми схемами.

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

Один питомец — множество сеансов
В активной области чата одновременно отображается только один питомец. Его положение и размер сохраняются для всех чатов и окон, а также остаются неизменными после перезапуска VS Code. То есть питомец помнит, где вы его оставили.

Что дальше?
Значит ли это, что освободившееся время стоит тратить на игры с питомцем в редакторе? Решать вам.

Источник: https://laurentkempe.com/2026/09/26/csharp-15-collection-expression-arguments/
This media is not supported in your browser
VIEW IN TELEGRAM
👍5👎3
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
День 2804. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.

48. Оптимизация производительности Entity Framework Core
«Как бы вы оптимизировали производительность Entity Framework Core? Приведите конкретные примеры методов и настроек, которые вы бы использовали для повышения эффективности взаимодействия с базой данных».

Хороший ответ
Оптимизация Entity Framework Core включает в себя ряд стратегий, направленных на минимизацию накладных расходов и повышение скорости доступа к данным.

Если в текущем контексте не требуется обновление данных, использование метода AsNoTracking позволяет существенно повысить производительность за счёт снижения накладных расходов на отслеживание изменений:
var products = await
dbContext.Products.AsNoTracking().ToListAsync();


Также полезно избегать использования ленивой загрузки (lazy loading) в ситуациях, которые могут привести к проблеме «N+1 запросов». Вместо этого лучше использовать явную или жадную загрузку (eager loading) для получения всех необходимых данных одним запросом:
var order = await dbContext.Orders
.Where(o => o.Id == orderId)
.Include(o => o.OrderItems)
.ThenInclude(oi => oi.Product)
.SingleOrDefaultAsync();


Фильтрация данных, получаемых из базы, и ограничение их объёма только тем, что действительно необходимо. Применение фильтров на уровне БД (вместо извлечения всех записей и последующей фильтрации в оперативной памяти) позволяет существенно сократить задержки и снизить потребление памяти.

Важно убедиться, что в БД корректно используются индексы для ускорения выполнения запросов — особенно для столбцов, часто фигурирующих в предложениях WHERE или условиях JOIN.

Регулярное профилирование SQL-запросов, генерируемых EF Core, с помощью таких инструментов, как SQL Profiler или встроенные средства логирования, позволяет выявлять неэффективные запросы и оптимизировать их.

Внедрение этих практик позволит значительно повысить производительность приложений, использующих EF Core, сделав их более отзывчивыми и масштабируемыми.

Часто встречающийся неудачный ответ
«Важно использовать .Include() для связанных данных, чтобы избежать выполнения множества запросов к базе. Это просто и гарантирует, что все данные будут загружены за один запрос».

Почему этот подход неверен
- Чрезмерное использование жадной загрузки: Беспорядочное применение .Include() может привести к загрузке избыточного объёма данных (особенно при подтягивании нескольких связанных сущностей). Это существенно увеличивает потребление памяти и снижает производительность.

- Увеличение объёма передаваемых данных и рост задержек: Загрузка всех связанных данных одним запросом без учёта реальных потребностей приложения приводит к передаче больших объёмов информации и увеличению задержек. Это особенно критично в условиях высокой сетевой нагрузки или при большом количестве одновременных обращений к приложению.

- Отсутствие точечной оптимизации запросов: Такой подход свидетельствует о непонимании тонкостей работы EF Core и игнорировании более эффективных методов — например, явной загрузки (explicit loading) или выборочной проекции (selective projection), — которые могут обеспечить более высокую производительность.

Эта распространённая ошибка часто возникает из-за непонимания стратегий загрузки данных в EF Core и недостаточного опыта оптимизации производительности при работе со сложными ORM-системами.

Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md