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

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
Недавно обновлял резюме и наткнулся на старую версию из 2018 года. Ох, были же времена, когда гордо писали: «уверенный пользователь ПК, MS Office» 😄 А ведь, сейчас этим уже никого не удивишь

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

Один из способов прокачать этот навык — магистратура «Управление внедрением ИИ в бизнес» от МИФИ и «Школы 21».

Вы научитесь:
— работать с данными, Python, ML и нейросетями
— запускать и развивать ИИ-продукты от идеи до MVP
— управлять командами и цифровыми продуктами

Что дает обучение:
— онлайн-формат с регулярными очными интенсивами;
— студенческий билет, льготы и доступ к инфраструктуре «Школы 21»;
— отсрочка от срочной службы;

Подать заявку и узнать все подробности можно здесь.

#реклама Рекламодатель АНО «Школа 21». ИНН 7736316133
👎21👍1
День 2726. #TipsAndTricks
Исправляем Ошибку «Слишком длинное имя файла» в Windows для Git

Бывает, что при клонировании или извлечении репозитория в Windows Git выдаёт следующую ошибку:
error: unable to create file some/very/deeply/nested/path/to/a/file.ts: Filename too long (невозможно создать файл … Имя файла слишком длинное)

С вашим кодом всё в порядке, с репозиторием тоже. Проблема в Windows.

Что происходит?
В Windows существует ограничение на длину пути по умолчанию в 260 символов (печально известный MAX_PATH). Операции Git, создающие файлы с полным путём длиннее этого, завершаются с этой ошибкой. Репозитории с глубоко вложенной структурой папок (например, node_modules или сгенерированный код) постоянно сталкиваются с этой проблемой.

Решение: разрешить длинные пути в Git
В Git есть параметр конфигурации именно для этого: core.longpaths. У вас есть два способа установить его, в зависимости от ваших прав на машине.

Системно (требует прав администратора):
git config --system core.longpaths true


На уровне пользователя (не требуется прав администратора):
git config --global core.longpaths true


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

Примечание: это только указывает Git на необходимость поддержки длинных путей, но не решает всей проблемы. Для полноценной работы некоторых инструментов и API в Windows также требуется включение поддержки длинных путей на уровне ОС.

Включение длинных путей в Windows
Если вы хотите, чтобы длинные пути поддерживались на уровне всей системы (другие инструменты, Проводник и т. д.), вам также необходимо включить их в самой Windows. Откройте Group Policy Editor (Редактор Групповой Политики - gpedit.msc) — только для версий Enterprise/Pro. Перейдите в Computer Configuration > Administrative Templates > System > Filesystem (Конфигурация компьютера > Административные шаблоны > Система > Файловая система. Включите параметр Enable Win32 long paths (Включить длинные пути Win32).

Или через реестр, если Редактор Групповой Политики недоступен (например, Windows Home):
reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1

Чтобы изменение вступило в силу, потребуется перезагрузка.

Источник:
https://bartwullems.blogspot.com/2026/07/fixing-filename-too-long-errors-on.html
День 2727. #ВопросыНаСобеседовании
Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.


40. Проблемы микросервисной архитектуры
«Какие проблемы возникают при внедрении микросервисной архитектуры в приложениях .NET, и как бы вы их решили?»

Хороший ответ
Внедрение микросервисной архитектуры в приложениях .NET сопряжено с рядом проблем, требующих тщательного рассмотрения и стратегического планирования для эффективного решения. Вот основные проблемы и стратегии по их преодолению.

1. Сложность координации сервисов: Микросервисы требуют сложной координации, поскольку каждый сервис разрабатывается, развёртывается и масштабируется независимо. Это может привести к проблемам с согласованностью данных и межсервисным взаимодействием. Для решения этой проблемы можно использовать инструменты оркестровки, такие как .NET Aspire во время локальной разработки и Kubernetes в производственной среде для управления развёртыванием и масштабированием сервисов. Поможет реализация Event-driven архитектуры или использование системы обмена сообщениями, такой как RabbitMQ, для обеспечения надежной связи между сервисами.

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

3. Отладка и мониторинг: Поскольку каждый сервис работает независимо, выявление и диагностика сбоев может быть сложной. Для решения этой проблемы реализуют централизованное логирование и мониторинг с использованием таких инструментов, как OpenTelemetry, Prometheus и Grafana. Также используют идентификаторы корреляции для отслеживания запросов между сервисами на разных уровнях и между самими сервисами.

4. Проблемы безопасности: Микросервисы увеличивают площадь поверхности для потенциальных угроз безопасности, поскольку данные перемещаются через границы сети. Для решения этой проблемы используют защищённые соединения HTTPS и решения для управления идентификацией и доступом (Identity and Access Management - IAM), такие как IdentityServer, для аутентификации и авторизации между сервисами.

5. Сложность развёртывания: Независимое развёртывание сервисов может привести к проблемам с версионированием и совместимостью. Для решения этой проблемы можно использовать контейнеры Docker для согласованной упаковки и развёртывания сервисов. Требуется тщательно управлять версиями сервисов и использовать API-шлюзы для обработки запросов к соответствующим версиям сервисов.

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

Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
👍5👎3
День 2728. #ЗаметкиНаПолях
Сравнение Чисел в .NET
Когда люди сравнивают числа, они обычно ожидают, что равенство означает одинаковые значения. Для чисел с плавающей точкой (Half, float и double) в .NET существуют два понятия равенства:
1. Семантика сравнения IEEE, используемая оператором ==,
2. Семантика эквивалентности для объектов .NET, используемая методом Equals.

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

Краткое сравнение
Для чисел Half, double и float важны следующие крайние случаи:
1. NaN и NaN
- == = false
- Equals = true
- CompareTo = 0

2. +0.0 и -0.0
- == = true
- Equals = true
- CompareTo = 0

3. +Infinity и +Infinity
- == = true
- Equals = true
- CompareTo = 0

4. -Infinity и +Infinity
- == = false
- Equals = false
- CompareTo < 0

5. NaN и конечное число
- == = false, a != = true
- Equals = false
- NaN.CompareTo(x) < 0

Оператор == соответствует правилам сравнения чисел с плавающей запятой из IEEE 754 / IEC 60559. Equals разработан для поддержки контрактов равенства .NET, используемых коллекциями и словарями.

Почему NaN == NaN ложно, а NaN.Equals(NaN) истинно?
NaN означает «Не число». Это специальное значение IEEE 754, используемое, когда операция не определена, например, деление на 0 (0.0 / 0.0).

IEEE 754 рассматривает NaN как неупорядоченное значение при сравнениях, т.е.:
- x == y ложно, если хотя бы одна сторона NaN;
- x < y, x > y, x <= y, x >= y ложно, если хотя бы одна сторона NaN;
- x != y истинно, если хотя бы одна сторона NaN;
Таким образом:
double x = double.NaN;

Console.WriteLine(x == x); // False
Console.WriteLine(x != x); // True
Console.WriteLine(x < 0); // False
Console.WriteLine(x >= 0); // False


Чтобы проверить, что значение является NaN, используйте API типа:
Half h = Half.NaN;
float f = float.NaN;
double d = double.NaN;

Console.WriteLine(Half.IsNaN(h)); // True
Console.WriteLine(float.IsNaN(f)); // True
Console.WriteLine(double.IsNaN(d)); // True

Но .NET также нуждается в понятии равенства, которое работает с контейнерами на основе хэшей. Если бы оператор Equals соответствовал стилю IEEE для NaN, это нарушило бы рефлексивность (x.Equals(x) должно быть true), и ключи, содержащие NaN, вели бы себя некорректно в словарях/хэшсетах. Поэтому Half.Equals, Double.Equals и Single.Equals обрабатывают NaN особым образом и возвращают true, когда оба значения являются NaN.

Окончание следует…

Источник:
https://www.meziantou.net/number-comparison-in-dotnet-equals-and-ieee-754-edge-cases.htm
👍3
День 2729. #ЗаметкиНаПолях
Сравнение Чисел в .NET. Окончание

Начало

+0.0 и -0.0: равны, но не идентичны
В стандарте IEEE 754 используется знаковый ноль. +0.0 и -0.0 сравниваются как равные, поэтому == и Equals возвращают true:
double pz = +0.0;
double nz = -0.0;

Console.WriteLine(pz == nz); // True
Console.WriteLine(pz.Equals(nz)); // True

Однако знак всё же имеет значение для некоторых операций:
Console.WriteLine(1.0 / +0.0); // +Infinity
Console.WriteLine(1.0 / -0.0); // -Infinity

Таким образом, «равенство» не всегда означает «взаимозаменяемость в каждом выражении».

Примечание: значения NaN также имеют знак. Такие методы, как float.IsNegative, возвращают true для -NaN.

CompareTo обеспечивает упорядочивание, включая обработку NaN
Операторы сравнения с NaN намеренно неудобны, поскольку NaN не упорядочен. Для сортировки .NET предоставляет возможность упорядочивания через CompareTo.

Для Half, double и float:
- NaN равно NaN;
- NaN меньше, чем не-NaN.
Это поведение явно закодировано в реализациях CompareTo в исходном коде среды выполнения.

Хэши нормализованы для NaN и знакового нуля
Еще один тонкий, но важный момент: GetHashCode() намеренно канонизирует значения. В методах Half.GetHashCode, Double.GetHashCode и Single.GetHashCode .NET гарантирует, что:
- все шаблоны битов NaN дают одинаковый хэш;
- +0.0 и -0.0 дают одинаковый хэш.
Это необходимо для согласованности с Equals, когда значения используются в качестве ключей.

Особый случай точности: значения, которые кажутся равными, могут быть не равными
Отдельным источником путаницы является представление. Многие десятичные значения не могут быть точно выражены в двоичном представлении с плавающей запятой, поэтому прямое сравнение на равенство часто не работает:
Console.WriteLine(0.1 + 0.2 == 0.3); // False

Тип decimal решает эту проблему, поскольку хранит целое число в десятичной системе счисления, а не дробь в двоичной системе. Такие значения, как 0.1m, 0.2m и 0.3m, точно воспроизводимы, поэтому:
Console.WriteLine(0.1m + 0.2m == 0.3m); // True

Точность decimal составляет от 28 до 29 значащих цифр. Внутри используется 96-битное целое число плюс коэффициент масштабирования (от 0 до 28 десятичных знаков) и знак.

Важные ограничения:
- decimal не является числом с произвольной точностью. Оно по-прежнему имеет конечный диапазон и может переполняться;
- Операции, которые дают более 28–29 значащих цифр, округляются;
- decimal относится к точному десятичному представлению, а не к поведению чисел с плавающей запятой по стандарту IEEE. В нём нет значений NaN или Infinity.

Для числовых алгоритмов сравнивайте с допуском (абсолютным + относительным), а не с Double.Epsilon:
static bool NearlyEqual(
double a,
double b,
double relTol = 1e-12,
double absTol = 1e-15)
{
if (a == b)
return true; // нули

if (double.IsNaN(a) || double.IsNaN(b))
return false;

if (double.IsInfinity(a) || double.IsInfinity(b))
return false;

double diff = Math.Abs(a - b);
double scale = Math.Max(Math.Abs(a), Math.Abs(b));
return diff <= Math.Max(absTol, relTol * scale);
}


Практические рекомендации
Используйте:
- ==, когда явно нужна семантика сравнения IEEE;
- Equals, когда нужна семантика равенства .NET (особенно в коллекциях);
- Half.IsNaN, double.IsNaN или float.IsNaN для проверки на NaN;
- сравнение с погрешностью для вычисленных результатов с плавающей запятой;
- decimal, когда нужны точные десятичные дроби (например, деньги) и когда достаточно 28-29 значащих цифр.

Итого
И ==, и Equals являются корректными. Они отвечают на разные вопросы:
- ==: «Равны ли эти значения согласно правилам сравнения чисел с плавающей запятой IEEE?»
- Equals: «Следует ли считать эти два значения .NET равными для контрактов равенства объектов?»
Как только вы разделите эти два намерения, крайние случаи, связанные с NaN, знаковым нулем и бесконечностью, станут предсказуемыми.

Источник:
https://www.meziantou.net/number-comparison-in-dotnet-equals-and-ieee-754-edge-cases.htm
👍2